blob: a769ad1b5ddb312062f677be4658f85848199b6f [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
Alexander Couzensda1bf8e2021-01-25 16:27:33 +01004/* (C) 2020 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
Alexander Couzens6a161492020-07-12 13:45:50 +02005 * Author: Alexander Couzens <lynxis@fe80.eu>
6 *
7 * All Rights Reserved
8 *
9 * SPDX-License-Identifier: GPL-2.0+
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23 *
24 */
25
26#include <stdlib.h>
27#include <unistd.h>
28#include <errno.h>
29#include <stdint.h>
30
31#include <arpa/inet.h>
Alexander Couzens841817e2020-11-19 00:41:29 +010032#include <net/if.h>
Alexander Couzens6a161492020-07-12 13:45:50 +020033
Alexander Couzens6a161492020-07-12 13:45:50 +020034#include <osmocom/core/byteswap.h>
Daniel Willmanndbab7142020-11-18 14:19:56 +010035#include <osmocom/core/fsm.h>
Pau Espin Pedrolcaf53172021-01-28 13:37:50 +010036#include <osmocom/core/linuxlist.h>
Alexander Couzensda1bf8e2021-01-25 16:27:33 +010037#include <osmocom/core/msgb.h>
38#include <osmocom/core/rate_ctr.h>
39#include <osmocom/core/select.h>
40#include <osmocom/core/talloc.h>
41#include <osmocom/core/sockaddr_str.h>
Alexander Couzens6a161492020-07-12 13:45:50 +020042#include <osmocom/core/socket.h>
Alexander Couzens841817e2020-11-19 00:41:29 +010043#include <osmocom/gprs/frame_relay.h>
Alexander Couzens6a161492020-07-12 13:45:50 +020044#include <osmocom/gprs/gprs_ns2.h>
45#include <osmocom/gsm/tlv.h>
Alexander Couzens6a161492020-07-12 13:45:50 +020046#include <osmocom/vty/command.h>
47#include <osmocom/vty/logging.h>
Pau Espin Pedrolcaf53172021-01-28 13:37:50 +010048#include <osmocom/vty/misc.h>
Alexander Couzensda1bf8e2021-01-25 16:27:33 +010049#include <osmocom/vty/telnet_interface.h>
50#include <osmocom/vty/vty.h>
Alexander Couzens6a161492020-07-12 13:45:50 +020051
52#include "gprs_ns2_internal.h"
53
Daniel Willmanncb3e9b52020-12-02 15:50:22 +010054#define SHOW_NS_STR "Display information about the NS protocol\n"
Alexander Couzensda1bf8e2021-01-25 16:27:33 +010055#define NSVCI_STR "NS Virtual Connection ID (NS-VCI)\n"
56#define DLCI_STR "Data Link connection identifier\n"
Pau Espin Pedrolcaf53172021-01-28 13:37:50 +010057
58static struct gprs_ns2_inst *vty_nsi = NULL;
Pau Espin Pedrolcaf53172021-01-28 13:37:50 +010059static struct osmo_fr_network *vty_fr_network = NULL;
Alexander Couzensda1bf8e2021-01-25 16:27:33 +010060static struct llist_head binds;
Alexander Couzens6b9d2322021-02-12 03:17:59 +010061static struct llist_head nses;
Pau Espin Pedrolcaf53172021-01-28 13:37:50 +010062
Alexander Couzensda1bf8e2021-01-25 16:27:33 +010063struct vty_bind {
64 struct llist_head list;
65 const char *name;
66 enum gprs_ns2_ll ll;
67 int dscp;
68 bool accept_ipaccess;
69 bool accept_sns;
Alexander Couzensc4704762021-02-08 23:13:12 +010070 uint8_t ip_sns_sig_weight;
71 uint8_t ip_sns_data_weight;
Alexander Couzensda1bf8e2021-01-25 16:27:33 +010072};
73
Alexander Couzens6b9d2322021-02-12 03:17:59 +010074struct vty_nse {
75 struct llist_head list;
76 uint16_t nsei;
77 /* list of binds which are valid for this nse. Only IP-SNS uses this
78 * to allow `no listen ..` in the bind context. So "half" created binds are valid for
79 * IP-SNS. This allows changing the bind ip without modifying all NSEs afterwards */
80 struct llist_head binds;
81};
82
83/* used by IP-SNS to connect multiple vty_nse_bind to a vty_nse */
84struct vty_nse_bind {
85 struct llist_head list;
86 struct vty_bind *vbind;
87};
88
Alexander Couzensda1bf8e2021-01-25 16:27:33 +010089/* TODO: this should into osmo timer */
Alexander Couzens6a161492020-07-12 13:45:50 +020090static const struct value_string gprs_ns_timer_strs[] = {
91 { 0, "tns-block" },
92 { 1, "tns-block-retries" },
93 { 2, "tns-reset" },
94 { 3, "tns-reset-retries" },
95 { 4, "tns-test" },
96 { 5, "tns-alive" },
97 { 6, "tns-alive-retries" },
98 { 7, "tsns-prov" },
Harald Welte33c3c062020-12-16 11:59:19 +010099 { 8, "tsns-size-retries" },
100 { 9, "tsns-config-retries" },
Alexander Couzens6a161492020-07-12 13:45:50 +0200101 { 0, NULL }
102};
103
Alexander Couzensda1bf8e2021-01-25 16:27:33 +0100104const struct value_string vty_fr_role_names[] = {
105 { FR_ROLE_USER_EQUIPMENT, "fr" },
106 { FR_ROLE_NETWORK_EQUIPMENT, "frnet" },
107 { 0, NULL }
108};
109
110const struct value_string vty_ll_names[] = {
111 { GPRS_NS2_LL_FR, "fr" },
112 { GPRS_NS2_LL_FR_GRE, "frgre" },
113 { GPRS_NS2_LL_UDP, "udp" },
114 { 0, NULL }
115};
116
117static struct vty_bind *vty_bind_by_name(const char *name)
Daniel Willmann751977b2020-12-02 18:59:44 +0100118{
Alexander Couzensda1bf8e2021-01-25 16:27:33 +0100119 struct vty_bind *vbind;
120 llist_for_each_entry(vbind, &binds, list) {
Alexander Couzensb7921732021-02-12 03:08:42 +0100121 if (!strcmp(vbind->name, name))
Alexander Couzensda1bf8e2021-01-25 16:27:33 +0100122 return vbind;
Daniel Willmann751977b2020-12-02 18:59:44 +0100123 }
Alexander Couzensda1bf8e2021-01-25 16:27:33 +0100124 return NULL;
Daniel Willmann751977b2020-12-02 18:59:44 +0100125}
126
Alexander Couzensda1bf8e2021-01-25 16:27:33 +0100127static struct vty_bind *vty_bind_alloc(const char *name)
Alexander Couzens6a161492020-07-12 13:45:50 +0200128{
Alexander Couzensda1bf8e2021-01-25 16:27:33 +0100129 struct vty_bind *vbind = talloc_zero(vty_nsi, struct vty_bind);
130 if (!vbind)
131 return NULL;
132
133 vbind->name = talloc_strdup(vty_nsi, name);
134 if (!vbind->name) {
135 talloc_free(vbind);
136 return NULL;
Alexander Couzens6a161492020-07-12 13:45:50 +0200137 }
Alexander Couzensda1bf8e2021-01-25 16:27:33 +0100138
Alexander Couzensc4704762021-02-08 23:13:12 +0100139 vbind->ip_sns_sig_weight = 1;
140 vbind->ip_sns_data_weight = 1;
Alexander Couzensda1bf8e2021-01-25 16:27:33 +0100141 llist_add(&vbind->list, &binds);
142 return vbind;
143}
144
145static void vty_bind_free(struct vty_bind *vbind)
146{
147 if (!vbind)
148 return;
149
150 llist_del(&vbind->list);
Alexander Couzens3e2e4a02021-02-09 16:15:06 +0100151 talloc_free(vbind);
Alexander Couzens6a161492020-07-12 13:45:50 +0200152}
153
Alexander Couzens6b9d2322021-02-12 03:17:59 +0100154static struct vty_nse *vty_nse_by_nsei(uint16_t nsei)
155{
156 struct vty_nse *vnse;
157 llist_for_each_entry(vnse, &nses, list) {
158 if (vnse->nsei == nsei)
159 return vnse;
160 }
161 return NULL;
162}
163
164static struct vty_nse *vty_nse_alloc(uint16_t nsei)
165{
166 struct vty_nse *vnse = talloc_zero(vty_nsi, struct vty_nse);
167 if (!vnse)
168 return NULL;
169
170 vnse->nsei = nsei;
171 INIT_LLIST_HEAD(&vnse->binds);
172 llist_add(&vnse->list, &nses);
173 return vnse;
174}
175
176static void vty_nse_free(struct vty_nse *vnse)
177{
178 if (!vnse)
179 return;
180
181 llist_del(&vnse->list);
182 /* all vbind of the nse will be freed by talloc */
183 talloc_free(vnse);
184}
185
186static int vty_nse_add_vbind(struct vty_nse *vnse, struct vty_bind *vbind)
187{
188 struct vty_nse_bind *vnse_bind;
189
190 if (vbind->ll != GPRS_NS2_LL_UDP)
191 return -EINVAL;
192
193 llist_for_each_entry(vnse_bind, &vnse->binds, list) {
194 if (vnse_bind->vbind == vbind)
195 return -EALREADY;
196 }
197
198 vnse_bind = talloc(vnse, struct vty_nse_bind);
199 if (!vnse_bind)
200 return -ENOMEM;
201 vnse_bind->vbind = vbind;
202
203 llist_add_tail(&vnse_bind->list, &vnse->binds);
204 return 0;
205}
206
207static int vty_nse_remove_vbind(struct vty_nse *vnse, struct vty_bind *vbind)
208{
209 struct vty_nse_bind *vnse_bind, *tmp;
210 if (vbind->ll != GPRS_NS2_LL_UDP)
211 return -EINVAL;
212
213 llist_for_each_entry_safe(vnse_bind, tmp, &vnse->binds, list) {
214 if (vnse_bind->vbind == vbind) {
215 llist_del(&vnse_bind->list);
216 talloc_free(vnse_bind);
217 }
218 }
219
220 return -ENOENT;
221}
222
223/* check if the NSE still has SNS configuration */
224static bool vty_nse_check_sns(struct gprs_ns2_nse *nse) {
225 struct vty_nse *vnse = vty_nse_by_nsei(nse->nsei);
226
227 int count = gprs_ns2_sns_count(nse);
228 if (count > 0) {
229 /* there are other sns endpoints */
230 return true;
231 }
232
233 if (!vnse)
234 return false;
235
236 if (llist_empty(&vnse->binds))
237 return false;
238
239 return true;
240}
241
Alexander Couzens6a161492020-07-12 13:45:50 +0200242static struct cmd_node ns_node = {
243 L_NS_NODE,
244 "%s(config-ns)# ",
245 1,
246};
247
Alexander Couzens6a161492020-07-12 13:45:50 +0200248DEFUN(cfg_ns, cfg_ns_cmd,
249 "ns",
250 "Configure the GPRS Network Service")
251{
252 vty->node = L_NS_NODE;
253 return CMD_SUCCESS;
254}
255
Alexander Couzensda1bf8e2021-01-25 16:27:33 +0100256DEFUN(cfg_ns_timer, cfg_ns_timer_cmd,
257 "timer " NS_TIMERS " <0-65535>",
258 "Network Service Timer\n"
259 NS_TIMERS_HELP "Timer Value\n")
260{
261 int idx = get_string_value(gprs_ns_timer_strs, argv[0]);
262 int val = atoi(argv[1]);
263
264 if (idx < 0 || idx >= ARRAY_SIZE(vty_nsi->timeout))
265 return CMD_WARNING;
266
267 vty_nsi->timeout[idx] = val;
268
269 return CMD_SUCCESS;
270}
271
272DEFUN(cfg_ns_nsei, cfg_ns_nsei_cmd,
273 "nse <0-65535>",
274 "Persistent NS Entity\n"
275 "NS Entity ID (NSEI)\n"
276 )
277{
278 struct gprs_ns2_nse *nse;
Alexander Couzens6b9d2322021-02-12 03:17:59 +0100279 struct vty_nse *vnse;
Alexander Couzensda1bf8e2021-01-25 16:27:33 +0100280 uint16_t nsei = atoi(argv[0]);
Alexander Couzens6b9d2322021-02-12 03:17:59 +0100281 bool free_vnse = false;
282
283 vnse = vty_nse_by_nsei(nsei);
284 if (!vnse) {
285 vnse = vty_nse_alloc(nsei);
286 if (!vnse) {
287 vty_out(vty, "Failed to create vty NSE!%s", VTY_NEWLINE);
288 return CMD_ERR_INCOMPLETE;
289 }
290 free_vnse = true;
291 }
Alexander Couzensda1bf8e2021-01-25 16:27:33 +0100292
293 nse = gprs_ns2_nse_by_nsei(vty_nsi, nsei);
294 if (!nse) {
295 nse = gprs_ns2_create_nse(vty_nsi, nsei, GPRS_NS2_LL_UNDEF, GPRS_NS2_DIALECT_UNDEF);
296 if (!nse) {
297 vty_out(vty, "Failed to create NSE!%s", VTY_NEWLINE);
Alexander Couzens6b9d2322021-02-12 03:17:59 +0100298 goto err;
Alexander Couzensda1bf8e2021-01-25 16:27:33 +0100299 }
300 nse->persistent = true;
301 }
302
303 if (!nse->persistent) {
304 /* TODO: should the dynamic NSE removed? */
305 vty_out(vty, "A dynamic NSE with the specified NSEI already exists%s", VTY_NEWLINE);
Alexander Couzens6b9d2322021-02-12 03:17:59 +0100306 goto err;
Alexander Couzensda1bf8e2021-01-25 16:27:33 +0100307 }
308
309 vty->node = L_NS_NSE_NODE;
310 vty->index = nse;
311
312 return CMD_SUCCESS;
Alexander Couzens6b9d2322021-02-12 03:17:59 +0100313
314err:
315 if (free_vnse)
316 talloc_free(vnse);
317
318 return CMD_ERR_INCOMPLETE;
Alexander Couzensda1bf8e2021-01-25 16:27:33 +0100319}
320
321DEFUN(cfg_no_ns_nsei, cfg_no_ns_nsei_cmd,
322 "no nse <0-65535>",
323 NO_STR
324 "Delete a Persistent NS Entity\n"
325 "NS Entity ID (NSEI)\n"
326 )
327{
328 struct gprs_ns2_nse *nse;
Alexander Couzens6b9d2322021-02-12 03:17:59 +0100329 struct vty_nse *vnse;
Alexander Couzensda1bf8e2021-01-25 16:27:33 +0100330 uint16_t nsei = atoi(argv[0]);
331
332 nse = gprs_ns2_nse_by_nsei(vty_nsi, nsei);
333 if (!nse) {
334 vty_out(vty, "Can not find NS Entity %s%s", argv[0], VTY_NEWLINE);
335 return CMD_ERR_NOTHING_TODO;
336 }
337
338 if (!nse->persistent) {
339 vty_out(vty, "Ignoring non-persistent NS Entity%s", VTY_NEWLINE);
340 return CMD_WARNING;
341 }
342
343 vty_out(vty, "Deleting NS Entity %u%s", nse->nsei, VTY_NEWLINE);
344 gprs_ns2_free_nse(nse);
Alexander Couzens6b9d2322021-02-12 03:17:59 +0100345
346 vnse = vty_nse_by_nsei(nsei);
347 vty_nse_free(vnse);
348
Alexander Couzensda1bf8e2021-01-25 16:27:33 +0100349 return CMD_SUCCESS;
350}
351
352/* TODO: add fr/gre */
353DEFUN(cfg_ns_bind, cfg_ns_bind_cmd,
354 "bind (fr|udp) ID",
Harald Welte2230a912021-03-04 20:09:50 +0100355 "Configure local Bind\n"
Alexander Couzensda1bf8e2021-01-25 16:27:33 +0100356 "Frame Relay\n" "UDP/IP\n"
Harald Welte2230a912021-03-04 20:09:50 +0100357 "Unique identifier for this bind (to reference from NS-VCs, NSEs, ...)\n"
Alexander Couzensda1bf8e2021-01-25 16:27:33 +0100358 )
359{
360 const char *nstype = argv[0];
361 const char *name = argv[1];
362 struct vty_bind *vbind;
363 enum gprs_ns2_ll ll;
364 int rc;
365
366 rc = get_string_value(vty_ll_names, nstype);
367 if (rc < 0)
368 return CMD_WARNING;
369 ll = (enum gprs_ns2_ll) rc;
370
371 if (!osmo_identifier_valid(name)) {
372 vty_out(vty, "Invalid ID. The ID should be only alphanumeric.%s", VTY_NEWLINE);
373 return CMD_WARNING;
374 }
375
376 vbind = vty_bind_by_name(name);
377 if (vbind) {
378 if (vbind->ll != ll) {
379 vty_out(vty, "A bind with the specified ID already exists with a different type (fr|frgre|udp)!%s",
380 VTY_NEWLINE);
381 return CMD_WARNING;
382 }
383 } else {
384 vbind = vty_bind_alloc(name);
385 if (!vbind) {
386 vty_out(vty, "Can not create bind - out of memory%s", VTY_NEWLINE);
387 return CMD_WARNING;
388 }
389 vbind->ll = ll;
390 }
391
392 vty->index = vbind;
393 vty->node = L_NS_BIND_NODE;
394
395 return CMD_SUCCESS;
396}
397
398DEFUN(cfg_no_ns_bind, cfg_no_ns_bind_cmd,
399 "no bind ID",
400 NO_STR
Harald Welte2230a912021-03-04 20:09:50 +0100401 "Delete a bind\n"
402 "Unique identifier for this bind\n"
Alexander Couzensda1bf8e2021-01-25 16:27:33 +0100403 )
404{
405 struct vty_bind *vbind;
406 struct gprs_ns2_vc_bind *bind;
407 const char *name = argv[0];
408
409 vbind = vty_bind_by_name(name);
410 if (!vbind) {
411 vty_out(vty, "bind %s does not exist!%s", name, VTY_NEWLINE);
412 return CMD_WARNING;
413 }
414 vty_bind_free(vbind);
415 bind = gprs_ns2_bind_by_name(vty_nsi, name);
416 if (bind)
417 bind->driver->free_bind(bind);
418 return CMD_SUCCESS;
419}
420
421
422static void config_write_vbind(struct vty *vty, struct vty_bind *vbind)
423{
424 struct gprs_ns2_vc_bind *bind;
425 const struct osmo_sockaddr *addr;
426 struct osmo_sockaddr_str addr_str;
427 const char *netif, *frrole_str, *llstr;
428 enum osmo_fr_role frrole;
429
430 llstr = get_value_string_or_null(vty_ll_names, vbind->ll);
431 if (!llstr)
432 return;
433 vty_out(vty, " bind %s %s%s", llstr, vbind->name, VTY_NEWLINE);
434
435 bind = gprs_ns2_bind_by_name(vty_nsi, vbind->name);
436 switch (vbind->ll) {
437 case GPRS_NS2_LL_FR:
438 if (bind) {
439 netif = gprs_ns2_fr_bind_netif(bind);
440 if (!netif)
441 return;
442 frrole = gprs_ns2_fr_bind_role(bind);
443 if ((int) frrole == -1)
444 return;
445 frrole_str = get_value_string_or_null(vty_fr_role_names, frrole);
446 if (netif && frrole_str)
447 vty_out(vty, " fr %s %s%s", netif, frrole_str, VTY_NEWLINE);
448 }
449 break;
450 case GPRS_NS2_LL_UDP:
451 if (bind) {
452 addr = gprs_ns2_ip_bind_sockaddr(bind);
453 if (!osmo_sockaddr_str_from_sockaddr(&addr_str, &addr->u.sas)) {
454 vty_out(vty, " listen %s %u%s", addr_str.ip, addr_str.port,
455 VTY_NEWLINE);
456 }
457 }
458 if (vbind->accept_ipaccess)
459 vty_out(vty, " accept-ipaccess%s", VTY_NEWLINE);
460 if (vbind->dscp)
461 vty_out(vty, " dscp %u%s", vbind->dscp, VTY_NEWLINE);
Daniel Willmann64db6362021-02-12 12:21:45 +0100462 vty_out(vty, " ip-sns signalling-weight %u data-weight %u%s",
Alexander Couzensc4704762021-02-08 23:13:12 +0100463 vbind->ip_sns_sig_weight, vbind->ip_sns_data_weight, VTY_NEWLINE);
Alexander Couzensda1bf8e2021-01-25 16:27:33 +0100464 break;
465 default:
466 return;
467 }
468}
469
470static void config_write_nsvc(struct vty *vty, const struct gprs_ns2_vc *nsvc)
471{
472 const char *netif;
473 uint16_t dlci;
474 const struct osmo_sockaddr *addr;
475 struct osmo_sockaddr_str addr_str;
476
477 switch (nsvc->nse->ll) {
478 case GPRS_NS2_LL_UNDEF:
479 break;
480 case GPRS_NS2_LL_UDP:
481 switch (nsvc->nse->dialect) {
482 case GPRS_NS2_DIALECT_IPACCESS:
483 addr = gprs_ns2_ip_vc_remote(nsvc);
484 if (!addr)
485 break;
486 if (osmo_sockaddr_str_from_sockaddr(&addr_str, &addr->u.sas))
487 break;
488 vty_out(vty, " nsvc ipa %s %s %u nsvci %u%s",
489 nsvc->bind->name, addr_str.ip, addr_str.port,
490 nsvc->nsvci, VTY_NEWLINE);
491 break;
492 case GPRS_NS2_DIALECT_STATIC_ALIVE:
493 addr = gprs_ns2_ip_vc_remote(nsvc);
494 if (!addr)
495 break;
496 if (osmo_sockaddr_str_from_sockaddr(&addr_str, &addr->u.sas))
497 break;
498 vty_out(vty, " nsvc udp %s %s %u%s",
499 nsvc->bind->name, addr_str.ip, addr_str.port, VTY_NEWLINE);
500 break;
501 default:
502 break;
503 }
504 break;
505 case GPRS_NS2_LL_FR:
506 netif = gprs_ns2_fr_bind_netif(nsvc->bind);
507 if (!netif)
508 break;
509 dlci = gprs_ns2_fr_nsvc_dlci(nsvc);
510 if (!dlci)
511 break;
512 OSMO_ASSERT(nsvc->nsvci_is_valid);
513 vty_out(vty, " nsvc fr %s dlci %u nsvci %u%s",
514 netif, dlci, nsvc->nsvci, VTY_NEWLINE);
515 break;
516 case GPRS_NS2_LL_FR_GRE:
517 break;
518 }
519}
520
521static void _config_write_ns_nse(struct vty *vty, struct gprs_ns2_nse *nse)
522{
523 struct gprs_ns2_vc *nsvc;
Alexander Couzens6b9d2322021-02-12 03:17:59 +0100524 struct vty_nse *vnse = vty_nse_by_nsei(nse->nsei);
525 struct vty_nse_bind *vbind;
526
527 OSMO_ASSERT(vnse);
Alexander Couzensda1bf8e2021-01-25 16:27:33 +0100528
529 vty_out(vty, " nse %u%s", nse->nsei, VTY_NEWLINE);
530 switch (nse->dialect) {
531 case GPRS_NS2_DIALECT_SNS:
532 ns2_sns_write_vty(vty, nse);
Alexander Couzens6b9d2322021-02-12 03:17:59 +0100533 llist_for_each_entry(vbind, &vnse->binds, list) {
534 vty_out(vty, " ip-sns-bind %s%s", vbind->vbind->name, VTY_NEWLINE);
535 }
Alexander Couzensda1bf8e2021-01-25 16:27:33 +0100536 break;
537 default:
538 llist_for_each_entry(nsvc, &nse->nsvc, list) {
539 config_write_nsvc(vty, nsvc);
540 }
541 break;
542 }
543}
544
Alexander Couzensda1bf8e2021-01-25 16:27:33 +0100545static int config_write_ns_nse(struct vty *vty)
546{
547 struct gprs_ns2_nse *nse;
548
549 llist_for_each_entry(nse, &vty_nsi->nse, list) {
550 if (!nse->persistent)
551 continue;
552
553 _config_write_ns_nse(vty, nse);
554 }
555
556 return 0;
557}
558
559static int config_write_ns_bind(struct vty *vty)
560{
561 struct vty_bind *vbind;
562
563 llist_for_each_entry(vbind, &binds, list) {
564 config_write_vbind(vty, vbind);
565 }
566
567 return 0;
568}
569
Alexander Couzens260cd522021-01-28 20:31:31 +0100570static int config_write_ns(struct vty *vty)
571{
572 unsigned int i;
573 int ret;
574
575 vty_out(vty, "ns%s", VTY_NEWLINE);
576
577 for (i = 0; i < ARRAY_SIZE(vty_nsi->timeout); i++)
578 vty_out(vty, " timer %s %u%s",
579 get_value_string(gprs_ns_timer_strs, i),
580 vty_nsi->timeout[i], VTY_NEWLINE);
581
582 ret = config_write_ns_bind(vty);
583 if (ret)
584 return ret;
585
586 ret = config_write_ns_nse(vty);
587 if (ret)
588 return ret;
589
590 return 0;
591}
592
593
Alexander Couzensda1bf8e2021-01-25 16:27:33 +0100594static struct cmd_node ns_bind_node = {
595 L_NS_BIND_NODE,
596 "%s(config-ns-bind)# ",
597 1,
598};
599
600DEFUN(cfg_ns_bind_listen, cfg_ns_bind_listen_cmd,
601 "listen " VTY_IPV46_CMD " <1-65535>",
Harald Welte2230a912021-03-04 20:09:50 +0100602 "Configure local IP + Port of this bind\n"
603 "Local IPv4 Address\n" "Local IPv6 Address\n"
604 "Local UDP Port\n"
Alexander Couzensda1bf8e2021-01-25 16:27:33 +0100605 )
606{
607 struct vty_bind *vbind = vty->index;
608 struct gprs_ns2_vc_bind *bind;
Alexander Couzens6b9d2322021-02-12 03:17:59 +0100609 int rc;
Alexander Couzensda1bf8e2021-01-25 16:27:33 +0100610 const char *addr_str = argv[0];
611 unsigned int port = atoi(argv[1]);
612 struct osmo_sockaddr_str sockaddr_str;
613 struct osmo_sockaddr sockaddr;
614
615 if (vbind->ll != GPRS_NS2_LL_UDP) {
616 vty_out(vty, "listen can be only used with UDP bind%s",
617 VTY_NEWLINE);
618 return CMD_WARNING;
619 }
620
621 if (osmo_sockaddr_str_from_str(&sockaddr_str, addr_str, port)) {
622 vty_out(vty, "Can not parse the Address %s %s%s", argv[0], argv[1], VTY_NEWLINE);
623 return CMD_WARNING;
624 }
625 osmo_sockaddr_str_to_sockaddr(&sockaddr_str, &sockaddr.u.sas);
626 if (gprs_ns2_ip_bind_by_sockaddr(vty_nsi, &sockaddr)) {
627 vty_out(vty, "A bind with the specified address already exists!%s", VTY_NEWLINE);
628 return CMD_WARNING;
629 }
630
Alexander Couzens6b9d2322021-02-12 03:17:59 +0100631 rc = gprs_ns2_ip_bind(vty_nsi, vbind->name, &sockaddr, vbind->dscp, &bind);
632 if (rc != 0) {
633 vty_out(vty, "Failed to create the bind (rc %d)!%s", rc, VTY_NEWLINE);
Alexander Couzensda1bf8e2021-01-25 16:27:33 +0100634 return CMD_WARNING;
635 }
636
637 bind->accept_ipaccess = vbind->accept_ipaccess;
638 bind->accept_sns = vbind->accept_sns;
639
640 return CMD_SUCCESS;
641}
642
643DEFUN(cfg_no_ns_bind_listen, cfg_no_ns_bind_listen_cmd,
644 "no listen",
645 NO_STR
646 "Delete a IP/Port assignment\n"
647 )
648{
649 struct vty_bind *vbind = vty->index;
650 struct gprs_ns2_vc_bind *bind;
651
652 if (vbind->ll != GPRS_NS2_LL_UDP) {
653 vty_out(vty, "no listen can be only used with UDP bind%s", VTY_NEWLINE);
654 return CMD_WARNING;
655 }
656
657 bind = gprs_ns2_bind_by_name(vty_nsi, vbind->name);
658 if (!bind)
659 return CMD_ERR_NOTHING_TODO;
660
Daniel Willmann90432052021-01-26 16:09:18 +0100661 OSMO_ASSERT(bind->ll == GPRS_NS2_LL_UDP);
Alexander Couzensda1bf8e2021-01-25 16:27:33 +0100662 bind->driver->free_bind(bind);
663 return CMD_SUCCESS;
664}
665
666DEFUN(cfg_ns_bind_dscp, cfg_ns_bind_dscp_cmd,
667 "dscp <0-255>",
668 "Set DSCP/TOS on the UDP socket\n" "DSCP Value\n")
669{
670 struct vty_bind *vbind = vty->index;
671 struct gprs_ns2_vc_bind *bind;
672 uint16_t dscp = atoi(argv[0]);
673
674 if (vbind->ll != GPRS_NS2_LL_UDP) {
675 vty_out(vty, "dscp can be only used with UDP bind%s",
676 VTY_NEWLINE);
677 return CMD_WARNING;
678 }
679
680 vbind->dscp = dscp;
681 bind = gprs_ns2_bind_by_name(vty_nsi, vbind->name);
682 if (bind)
683 gprs_ns2_ip_bind_set_dscp(bind, dscp);
684
685 return CMD_SUCCESS;
686}
687
688DEFUN(cfg_no_ns_bind_dscp, cfg_no_ns_bind_dscp_cmd,
689 "no dscp",
690 "Set DSCP/TOS on the UDP socket\n" "DSCP Value\n")
691{
692 struct vty_bind *vbind = vty->index;
693 struct gprs_ns2_vc_bind *bind;
694 uint16_t dscp = 0;
695
696 if (vbind->ll != GPRS_NS2_LL_UDP) {
697 vty_out(vty, "dscp can be only used with UDP bind%s",
698 VTY_NEWLINE);
699 return CMD_WARNING;
700 }
701
702 vbind->dscp = dscp;
703 bind = gprs_ns2_bind_by_name(vty_nsi, vbind->name);
704 if (bind)
705 gprs_ns2_ip_bind_set_dscp(bind, dscp);
706
707 return CMD_SUCCESS;
708}
709
710DEFUN(cfg_ns_bind_ipaccess, cfg_ns_bind_ipaccess_cmd,
711 "accept-ipaccess",
712 "Allow to create dynamic NS Entity by NS Reset PDU on UDP (ip.access style)\n"
713 )
714{
715 struct vty_bind *vbind = vty->index;
716 struct gprs_ns2_vc_bind *bind;
717
718 if (vbind->ll != GPRS_NS2_LL_UDP) {
719 vty_out(vty, "accept-ipaccess can be only used with UDP bind%s",
720 VTY_NEWLINE);
721 return CMD_WARNING;
722 }
723
724 vbind->accept_ipaccess = true;
725 bind = gprs_ns2_bind_by_name(vty_nsi, vbind->name);
726 if (bind)
727 bind->accept_ipaccess = true;
728
729 return CMD_SUCCESS;
730}
731
732DEFUN(cfg_no_ns_bind_ipaccess, cfg_no_ns_bind_ipaccess_cmd,
733 "no accept-ipaccess",
734 NO_STR
735 "Reject NS Reset PDU on UDP (ip.access style)\n"
736 )
737{
738 struct vty_bind *vbind = vty->index;
739 struct gprs_ns2_vc_bind *bind;
740
741 if (vbind->ll != GPRS_NS2_LL_UDP) {
742 vty_out(vty, "no accept-ipaccess can be only used with UDP bind%s",
743 VTY_NEWLINE);
744 return CMD_WARNING;
745 }
746
747 vbind->accept_ipaccess = false;
748 bind = gprs_ns2_bind_by_name(vty_nsi, vbind->name);
749 if (bind)
750 bind->accept_ipaccess = false;
751
752 return CMD_SUCCESS;
753}
754
Alexander Couzensc4704762021-02-08 23:13:12 +0100755DEFUN(cfg_ns_bind_ip_sns_weight, cfg_ns_bind_ip_sns_weight_cmd,
756 "ip-sns signalling-weight <0-254> data-weight <0-254>",
757 "IP SNS\n"
758 "signalling weight used by IP-SNS dynamic configuration\n"
759 "signalling weight used by IP-SNS dynamic configuration\n"
760 "data weight used by IP-SNS dynamic configuration\n"
761 "data weight used by IP-SNS dynamic configuration\n")
762{
763 struct vty_bind *vbind = vty->index;
764 struct gprs_ns2_vc_bind *bind;
765
766 int signalling = atoi(argv[0]);
767 int data = atoi(argv[1]);
768
769 if (vbind->ll != GPRS_NS2_LL_UDP) {
770 vty_out(vty, "ip-sns signalling-weight <0-254> data-weight <0-254> can be only used with UDP bind%s",
771 VTY_NEWLINE);
772 return CMD_WARNING;
773 }
774
775 vbind->ip_sns_data_weight = data;
776 vbind->ip_sns_sig_weight = signalling;
777 bind = gprs_ns2_bind_by_name(vty_nsi, vbind->name);
778 if (bind)
779 gprs_ns2_ip_bind_set_sns_weight(bind, signalling, data);
780
781 return CMD_SUCCESS;
782}
Alexander Couzensda1bf8e2021-01-25 16:27:33 +0100783
784DEFUN(cfg_ns_bind_fr, cfg_ns_bind_fr_cmd,
785 "fr NETIF (fr|frnet)",
786 "frame relay\n"
787 IFNAME_STR
788 "fr (user) is used by BSS or SGSN attached to UNI of a FR network\n"
789 "frnet (network) is used by SGSN if BSS is directly attached\n"
790 )
791{
792 struct vty_bind *vbind = vty->index;
793 struct gprs_ns2_vc_bind *bind;
794 const char *netif = argv[0];
795 const char *role = argv[1];
796
797 int rc = 0;
798 enum osmo_fr_role frrole;
799
800 if (vbind->ll != GPRS_NS2_LL_FR) {
801 vty_out(vty, "fr can be only used with frame relay bind%s", VTY_NEWLINE);
802 return CMD_WARNING;
803 }
804
805 if (!strcmp(role, "fr"))
806 frrole = FR_ROLE_USER_EQUIPMENT;
807 else if (!strcmp(role, "frnet"))
808 frrole = FR_ROLE_NETWORK_EQUIPMENT;
809 else
810 return CMD_WARNING;
811
812 bind = gprs_ns2_fr_bind_by_netif(vty_nsi, netif);
813 if (bind) {
814 vty_out(vty, "Interface %s already used.%s", netif, VTY_NEWLINE);
815 return CMD_WARNING;
816 }
817
818 rc = gprs_ns2_fr_bind(vty_nsi, vbind->name, netif, vty_fr_network, frrole, &bind);
819 if (rc < 0) {
820 LOGP(DLNS, LOGL_ERROR, "Failed to bind interface %s on fr. Err: %d\n", netif, rc);
821 return CMD_WARNING;
822 }
823
824 return CMD_SUCCESS;
825}
826
827DEFUN(cfg_no_ns_bind_fr, cfg_no_ns_bind_fr_cmd,
828 "no fr NETIF",
829 NO_STR
830 "Delete a frame relay link\n"
831 "Delete a frame relay link\n"
832 IFNAME_STR
833 )
834{
835 struct vty_bind *vbind = vty->index;
836 struct gprs_ns2_vc_bind *bind;
837 const char *netif = argv[0];
838
839 if (vbind->ll != GPRS_NS2_LL_FR) {
840 vty_out(vty, "fr can be only used with frame relay bind%s",
841 VTY_NEWLINE);
842 return CMD_WARNING;
843 }
844
845 bind = gprs_ns2_fr_bind_by_netif(vty_nsi, netif);
846 if (!bind) {
847 vty_out(vty, "Interface not found.%s", VTY_NEWLINE);
848 return CMD_WARNING;
849 }
850
851 if (strcmp(bind->name, vbind->name)) {
852 vty_out(vty, "The specified interface is not bound to this bind.%s", VTY_NEWLINE);
853 return CMD_WARNING;
854 }
855
856 bind->driver->free_bind(bind);
857 return CMD_SUCCESS;
858}
859
860
861static struct cmd_node ns_nse_node = {
862 L_NS_NSE_NODE,
863 "%s(config-ns-nse)# ",
864 1,
865};
866
867DEFUN(cfg_ns_nse_nsvc_fr, cfg_ns_nse_nsvc_fr_cmd,
868 "nsvc fr NETIF dlci <16-1007> nsvci <0-65535>",
869 "NS Virtual Connection\n"
870 "frame relay\n"
871 "frame relay interface. Must be registered via fr vty\n"
872 NSVCI_STR
873 NSVCI_STR
874 DLCI_STR
875 DLCI_STR
876 )
877{
878 struct gprs_ns2_vc_bind *bind;
879 struct gprs_ns2_vc *nsvc;
880 struct gprs_ns2_nse *nse = vty->index;
881 const char *netif = argv[0];
882 uint16_t dlci = atoi(argv[1]);
883 uint16_t nsvci = atoi(argv[2]);
884 bool dialect_modified = false;
885 bool ll_modified = false;
886
887 if (nse->ll != GPRS_NS2_LL_FR && nse->ll != GPRS_NS2_LL_UNDEF) {
888 vty_out(vty, "Can not mix NS-VC with different link layer%s", VTY_NEWLINE);
889 goto err;
890 }
891
892 if (nse->dialect != GPRS_NS2_DIALECT_STATIC_RESETBLOCK && nse->dialect != GPRS_NS2_DIALECT_UNDEF) {
893 vty_out(vty, "Can not mix NS-VC with different dialects%s", VTY_NEWLINE);
894 goto err;
895 }
896
897 if (nse->ll == GPRS_NS2_LL_UNDEF) {
898 nse->ll = GPRS_NS2_LL_FR;
899 ll_modified = true;
900 }
901
902 if (nse->dialect == GPRS_NS2_DIALECT_UNDEF) {
Harald Welte06d9bf92021-03-05 10:20:11 +0100903 ns2_nse_set_dialect(nse, GPRS_NS2_DIALECT_STATIC_RESETBLOCK);
Alexander Couzensda1bf8e2021-01-25 16:27:33 +0100904 dialect_modified = true;
905 }
906
907
908 bind = gprs_ns2_fr_bind_by_netif(vty_nsi, netif);
909 if (!bind) {
910 vty_out(vty, "Can not find fr interface \"%s\". Please configure it via fr vty.%s",
911 netif, VTY_NEWLINE);
912 goto err;
913 }
914
915 if (gprs_ns2_fr_nsvc_by_dlci(bind, dlci)) {
916 vty_out(vty, "A NS-VC with the specified DLCI already exist!%s", VTY_NEWLINE);
917 goto err;
918 }
919
920 if (gprs_ns2_nsvc_by_nsvci(vty_nsi, nsvci)) {
921 vty_out(vty, "A NS-VC with the specified NS-VCI already exist!%s", VTY_NEWLINE);
922 goto err;
923 }
924
925 nsvc = gprs_ns2_fr_connect(bind, nse, nsvci, dlci);
926 if (!nsvc) {
927 /* Could not create NS-VC, connect failed */
928 vty_out(vty, "Failed to create the NS-VC%s", VTY_NEWLINE);
929 goto err;
930 }
931 nsvc->persistent = true;
932 return CMD_SUCCESS;
933
934err:
935 if (ll_modified)
936 nse->ll = GPRS_NS2_LL_UNDEF;
937 if (dialect_modified)
Harald Welte06d9bf92021-03-05 10:20:11 +0100938 ns2_nse_set_dialect(nse, GPRS_NS2_DIALECT_UNDEF);
Alexander Couzensda1bf8e2021-01-25 16:27:33 +0100939
940 return CMD_WARNING;
941}
942
943DEFUN(cfg_no_ns_nse_nsvc_fr_dlci, cfg_no_ns_nse_nsvc_fr_dlci_cmd,
944 "no nsvc fr NETIF dlci <16-1007>",
945 NO_STR
946 "Delete frame relay NS-VC\n"
947 "frame relay\n"
948 "frame relay interface. Must be registered via fr vty\n"
949 DLCI_STR
950 DLCI_STR
951 )
952{
953 struct gprs_ns2_vc_bind *bind;
954 struct gprs_ns2_vc *nsvc;
955 struct gprs_ns2_nse *nse = vty->index;
956 const char *netif = argv[0];
957 uint16_t dlci = atoi(argv[1]);
958
959 if (nse->ll != GPRS_NS2_LL_FR) {
960 vty_out(vty, "This NSE doesn't support frame relay.%s", VTY_NEWLINE);
961 return CMD_WARNING;
962 }
963
964 bind = gprs_ns2_fr_bind_by_netif(vty_nsi, netif);
965 if (!bind) {
966 vty_out(vty, "Can not find fr interface \"%s\"%s",
967 netif, VTY_NEWLINE);
968 return CMD_ERR_NOTHING_TODO;
969 }
970
971 nsvc = gprs_ns2_fr_nsvc_by_dlci(bind, dlci);
972 if (!nsvc) {
973 vty_out(vty, "Can not find a NS-VC on fr interface %s with dlci %u%s",
974 netif, dlci, VTY_NEWLINE);
975 return CMD_WARNING;
976 }
977
978 if (nse != nsvc->nse) {
979 vty_out(vty, "The specified NS-VC is not a part of the NSE %u!%s"
980 "To remove this NS-VC go to the vty node 'nse %u'%s",
981 nse->nsei, VTY_NEWLINE,
982 nsvc->nse->nsei, VTY_NEWLINE);
983 return CMD_WARNING;
984 }
985
986 gprs_ns2_free_nsvc(nsvc);
987 if (llist_empty(&nse->nsvc)) {
988 nse->ll = GPRS_NS2_LL_UNDEF;
Harald Welte06d9bf92021-03-05 10:20:11 +0100989 ns2_nse_set_dialect(nse, GPRS_NS2_DIALECT_UNDEF);
Alexander Couzensda1bf8e2021-01-25 16:27:33 +0100990 }
991
992 return CMD_SUCCESS;
993}
994
995DEFUN(cfg_no_ns_nse_nsvci, cfg_no_ns_nse_nsvci_cmd,
996 "no nsvc nsvci <0-65535>",
997 NO_STR
998 "Delete NSVC\n"
999 NSVCI_STR
1000 NSVCI_STR
1001 )
1002{
1003 struct gprs_ns2_vc *nsvc;
1004 struct gprs_ns2_nse *nse = vty->index;
1005 uint16_t nsvci = atoi(argv[0]);
1006
1007 switch (nse->dialect) {
1008 case GPRS_NS2_DIALECT_SNS:
1009 case GPRS_NS2_DIALECT_STATIC_ALIVE:
1010 vty_out(vty, "NSE doesn't support NSVCI.%s", VTY_NEWLINE);
1011 return CMD_WARNING;
1012 case GPRS_NS2_DIALECT_UNDEF:
1013 vty_out(vty, "No NSVCs configured%s", VTY_NEWLINE);
1014 return CMD_WARNING;
1015 case GPRS_NS2_DIALECT_IPACCESS:
1016 case GPRS_NS2_DIALECT_STATIC_RESETBLOCK:
1017 break;
1018 }
1019
1020 nsvc = gprs_ns2_nsvc_by_nsvci(vty_nsi, nsvci);
1021 if (!nsvc) {
1022 vty_out(vty, "Can not find NS-VC with NS-VCI %u%s", nsvci, VTY_NEWLINE);
1023 return CMD_WARNING;
1024 }
1025
1026 if (nse != nsvc->nse) {
1027 vty_out(vty, "NS-VC with NS-VCI %u is not part of this NSE!%s",
1028 nsvci, VTY_NEWLINE);
1029 return CMD_WARNING;
1030 }
1031
1032 gprs_ns2_free_nsvc(nsvc);
1033 if (llist_empty(&nse->nsvc)) {
1034 nse->ll = GPRS_NS2_LL_UNDEF;
Harald Welte06d9bf92021-03-05 10:20:11 +01001035 ns2_nse_set_dialect(nse, GPRS_NS2_DIALECT_UNDEF);
Alexander Couzensda1bf8e2021-01-25 16:27:33 +01001036 }
1037
1038 return CMD_SUCCESS;
1039}
1040
Alexander Couzensbf5d0db2021-02-12 04:04:13 +01001041static int ns_nse_nsvc_udp_cmds(struct vty *vty, const char *bind_name, const char *remote_char, uint16_t port,
1042 uint16_t sig_weight, uint16_t data_weight)
Alexander Couzensda1bf8e2021-01-25 16:27:33 +01001043{
1044 struct gprs_ns2_vc_bind *bind;
1045 struct gprs_ns2_vc *nsvc;
1046 struct gprs_ns2_nse *nse = vty->index;
1047 bool dialect_modified = false;
1048 bool ll_modified = false;
1049
Alexander Couzensda1bf8e2021-01-25 16:27:33 +01001050 struct osmo_sockaddr_str remote_str;
1051 struct osmo_sockaddr remote;
Alexander Couzensda1bf8e2021-01-25 16:27:33 +01001052
1053 if (nse->ll == GPRS_NS2_LL_UNDEF) {
1054 nse->ll = GPRS_NS2_LL_UDP;
1055 ll_modified = true;
1056 }
1057
1058 if (nse->dialect == GPRS_NS2_DIALECT_UNDEF) {
Harald Welte06d9bf92021-03-05 10:20:11 +01001059 ns2_nse_set_dialect(nse, GPRS_NS2_DIALECT_STATIC_ALIVE);
Alexander Couzensda1bf8e2021-01-25 16:27:33 +01001060 dialect_modified = true;
1061 }
1062
1063 if (nse->ll != GPRS_NS2_LL_UDP) {
1064 vty_out(vty, "Can not mix NS-VC with different link layer%s", VTY_NEWLINE);
1065 goto err;
1066 }
1067
1068 if (nse->dialect != GPRS_NS2_DIALECT_STATIC_ALIVE) {
1069 vty_out(vty, "Can not mix NS-VC with different dialects%s", VTY_NEWLINE);
1070 goto err;
1071 }
1072
Alexander Couzensbf5d0db2021-02-12 04:04:13 +01001073 if (osmo_sockaddr_str_from_str(&remote_str, remote_char, port)) {
Alexander Couzensda1bf8e2021-01-25 16:27:33 +01001074 vty_out(vty, "Can not parse IPv4/IPv6 or port.%s", VTY_NEWLINE);
1075 goto err;
1076 }
1077
1078 if (osmo_sockaddr_str_to_sockaddr(&remote_str, &remote.u.sas)) {
1079 vty_out(vty, "Can not parse IPv4/IPv6 or port.%s", VTY_NEWLINE);
1080 goto err;
1081 }
1082
1083 bind = gprs_ns2_bind_by_name(vty_nsi, bind_name);
1084 if (!bind) {
1085 vty_out(vty, "Can not find bind with name %s%s",
1086 bind_name, VTY_NEWLINE);
1087 goto err;
1088 }
1089
1090 if (bind->ll != GPRS_NS2_LL_UDP) {
1091 vty_out(vty, "Bind %s is not an UDP bind.%s",
1092 bind_name, VTY_NEWLINE);
1093 goto err;
1094 }
1095
Alexander Couzens7bb39e32021-02-16 23:06:53 +01001096 nsvc = gprs_ns2_nsvc_by_sockaddr_bind(bind, &remote);
1097 if (nsvc) {
1098 if (nsvc->nse == nse)
1099 vty_out(vty, "Specified NSVC is already present in this NSE.%s", VTY_NEWLINE);
1100 else
1101 vty_out(vty, "Specified NSVC is already present in another NSE%05u.%s", nsvc->nse->nsei, VTY_NEWLINE);
1102 goto err;
1103 }
1104
Alexander Couzensda1bf8e2021-01-25 16:27:33 +01001105 nsvc = gprs_ns2_ip_connect(bind, &remote, nse, 0);
1106 if (!nsvc) {
1107 vty_out(vty, "Can not create NS-VC.%s", VTY_NEWLINE);
1108 goto err;
1109 }
Alexander Couzensbf5d0db2021-02-12 04:04:13 +01001110 nsvc->sig_weight = sig_weight;
1111 nsvc->data_weight = data_weight;
Alexander Couzensda1bf8e2021-01-25 16:27:33 +01001112 nsvc->persistent = true;
1113
1114 return CMD_SUCCESS;
1115
1116err:
1117 if (ll_modified)
1118 nse->ll = GPRS_NS2_LL_UNDEF;
1119 if (dialect_modified)
Harald Welte06d9bf92021-03-05 10:20:11 +01001120 ns2_nse_set_dialect(nse, GPRS_NS2_DIALECT_UNDEF);
Alexander Couzensda1bf8e2021-01-25 16:27:33 +01001121 return CMD_WARNING;
1122}
1123
Alexander Couzensbf5d0db2021-02-12 04:04:13 +01001124DEFUN(cfg_ns_nse_nsvc_udp, cfg_ns_nse_nsvc_udp_cmd,
1125 "nsvc udp BIND " VTY_IPV46_CMD " <1-65535>",
1126 "NS Virtual Connection\n"
1127 "NS over UDP\n"
1128 "A unique bind identifier created by ns bind\n"
1129 "Remote IPv4 Address\n" "Remote IPv6 Address\n"
1130 "Remote UDP Port\n")
1131{
1132 const char *bind_name = argv[0];
1133 const char *remote = argv[1];
1134 uint16_t port = atoi(argv[2]);
1135 uint16_t sig_weight = 1;
1136 uint16_t data_weight = 1;
1137
1138 return ns_nse_nsvc_udp_cmds(vty, bind_name, remote, port, sig_weight, data_weight);
1139}
1140
1141DEFUN(cfg_ns_nse_nsvc_udp_weights, cfg_ns_nse_nsvc_udp_weights_cmd,
1142 "nsvc udp BIND " VTY_IPV46_CMD " <1-65535> signalling-weight <0-254> data-weight <0-254>",
1143 "NS Virtual Connection\n"
1144 "NS over UDP\n"
1145 "A unique bind identifier created by ns bind\n"
1146 "Remote IPv4 Address\n" "Remote IPv6 Address\n"
1147 "Remote UDP Port\n"
1148 "Signalling weight of the NSVC (default = 1)\n"
1149 "Signalling weight of the NSVC (default = 1)\n"
1150 "Data weight of the NSVC (default = 1)\n"
1151 "Data weight of the NSVC (default = 1)\n"
1152 )
1153{
1154 const char *bind_name = argv[0];
1155 const char *remote = argv[1];
1156 uint16_t port = atoi(argv[2]);
1157 uint16_t sig_weight = atoi(argv[3]);
1158 uint16_t data_weight = atoi(argv[4]);
1159
1160 return ns_nse_nsvc_udp_cmds(vty, bind_name, remote, port, sig_weight, data_weight);
1161}
1162
Alexander Couzensda1bf8e2021-01-25 16:27:33 +01001163DEFUN(cfg_no_ns_nse_nsvc_udp, cfg_no_ns_nse_nsvc_udp_cmd,
1164 "no nsvc udp BIND " VTY_IPV46_CMD " <1-65535>",
1165 NO_STR
1166 "Delete a NS Virtual Connection\n"
1167 "NS over UDP\n"
1168 "A unique bind identifier created by ns bind\n"
1169 "Remote IPv4 Address\n" "Remote IPv6 Address\n"
1170 "Remote UDP Port\n"
1171 )
1172{
1173 struct gprs_ns2_vc_bind *bind;
1174 struct gprs_ns2_vc *nsvc;
1175 struct gprs_ns2_nse *nse = vty->index;
1176 const char *bind_name = argv[0];
1177 struct osmo_sockaddr_str remote_str;
1178 struct osmo_sockaddr remote;
1179 uint16_t port = atoi(argv[2]);
1180
1181 if (nse->ll != GPRS_NS2_LL_UDP) {
1182 vty_out(vty, "This NSE doesn't support UDP.%s", VTY_NEWLINE);
1183 return CMD_WARNING;
1184 }
1185
1186 if (nse->dialect != GPRS_NS2_DIALECT_STATIC_ALIVE) {
1187 vty_out(vty, "This NSE doesn't support UDP with dialect static alive.%s", VTY_NEWLINE);
1188 return CMD_WARNING;
1189 }
1190
1191 bind = gprs_ns2_bind_by_name(vty_nsi, bind_name);
1192 if (!bind) {
1193 vty_out(vty, "Can not find bind with name %s%s",
1194 bind_name, VTY_NEWLINE);
1195 return CMD_WARNING;
1196 }
1197
1198 if (bind->ll != GPRS_NS2_LL_UDP) {
1199 vty_out(vty, "Bind %s is not an UDP bind.%s",
1200 bind_name, VTY_NEWLINE);
1201 return CMD_WARNING;
1202 }
1203
1204 if (osmo_sockaddr_str_from_str(&remote_str, argv[1], port)) {
1205 vty_out(vty, "Can not parse IPv4/IPv6 or port.%s", VTY_NEWLINE);
1206 return CMD_WARNING;
1207 }
1208
1209 if (osmo_sockaddr_str_to_sockaddr(&remote_str, &remote.u.sas)) {
1210 vty_out(vty, "Can not parse IPv4/IPv6 or port.%s", VTY_NEWLINE);
1211 return CMD_WARNING;
1212 }
1213
1214 nsvc = gprs_ns2_nsvc_by_sockaddr_bind(bind, &remote);
1215 if (!nsvc) {
1216 vty_out(vty, "Can not find NS-VC with remote %s:%u%s",
1217 remote_str.ip, remote_str.port, VTY_NEWLINE);
1218 return CMD_WARNING;
1219 }
1220
1221 if (!nsvc->persistent) {
1222 vty_out(vty, "NS-VC with remote %s:%u is a dynamic NS-VC. Not configured by vty.%s",
1223 remote_str.ip, remote_str.port, VTY_NEWLINE);
1224 return CMD_WARNING;
1225 }
1226
1227 if (nsvc->nse != nse) {
1228 vty_out(vty, "NS-VC is not part of this NSE!%s", VTY_NEWLINE);
1229 return CMD_WARNING;
1230 }
1231
1232 gprs_ns2_free_nsvc(nsvc);
1233 if (llist_empty(&nse->nsvc)) {
1234 nse->ll = GPRS_NS2_LL_UNDEF;
Harald Welte06d9bf92021-03-05 10:20:11 +01001235 ns2_nse_set_dialect(nse, GPRS_NS2_DIALECT_UNDEF);
Alexander Couzensda1bf8e2021-01-25 16:27:33 +01001236 }
1237
1238 return CMD_SUCCESS;
1239}
1240
1241DEFUN(cfg_ns_nse_nsvc_ipa, cfg_ns_nse_nsvc_ipa_cmd,
1242 "nsvc ipa BIND " VTY_IPV46_CMD " <1-65535> nsvci <0-65535>" ,
1243 "NS Virtual Connection\n"
1244 "NS over UDP ip.access style (uses RESET/BLOCK)\n"
1245 "A unique bind identifier created by ns bind\n"
1246 "Remote IPv4 Address\n" "Remote IPv6 Address\n"
1247 "Remote UDP Port\n"
1248 NSVCI_STR
1249 NSVCI_STR
1250 )
1251{
1252 struct gprs_ns2_vc_bind *bind;
1253 struct gprs_ns2_vc *nsvc;
1254 struct gprs_ns2_nse *nse = vty->index;
1255 bool dialect_modified = false;
1256 bool ll_modified = false;
1257
1258 const char *bind_name = argv[0];
1259 struct osmo_sockaddr_str remote_str;
1260 struct osmo_sockaddr remote;
1261 uint16_t port = atoi(argv[2]);
1262 uint16_t nsvci = atoi(argv[3]);
1263
1264 if (nse->ll == GPRS_NS2_LL_UNDEF) {
1265 nse->ll = GPRS_NS2_LL_UDP;
1266 ll_modified = true;
1267 }
1268
1269 if (nse->dialect == GPRS_NS2_DIALECT_UNDEF) {
Harald Welte06d9bf92021-03-05 10:20:11 +01001270 ns2_nse_set_dialect(nse, GPRS_NS2_DIALECT_IPACCESS);
Alexander Couzensda1bf8e2021-01-25 16:27:33 +01001271 dialect_modified = true;
1272 }
1273
1274 if (nse->ll != GPRS_NS2_LL_UDP) {
1275 vty_out(vty, "Can not mix NS-VC with different link layer%s", VTY_NEWLINE);
1276 goto err;
1277 }
1278
1279 if (nse->dialect != GPRS_NS2_DIALECT_IPACCESS) {
1280 vty_out(vty, "Can not mix NS-VC with different dialects%s", VTY_NEWLINE);
1281 goto err;
1282 }
1283
1284 if (osmo_sockaddr_str_from_str(&remote_str, argv[1], port)) {
1285 vty_out(vty, "Can not parse IPv4/IPv6 or port.%s", VTY_NEWLINE);
1286 goto err;
1287 }
1288
1289 if (osmo_sockaddr_str_to_sockaddr(&remote_str, &remote.u.sas)) {
1290 vty_out(vty, "Can not parse IPv4/IPv6 or port.%s", VTY_NEWLINE);
1291 goto err;
1292 }
1293
1294 bind = gprs_ns2_bind_by_name(vty_nsi, bind_name);
1295 if (!bind) {
1296 vty_out(vty, "Can not find bind with name %s%s",
1297 bind_name, VTY_NEWLINE);
1298 goto err;
1299 }
1300
1301 if (bind->ll != GPRS_NS2_LL_UDP) {
1302 vty_out(vty, "Bind %s is not an UDP bind.%s",
1303 bind_name, VTY_NEWLINE);
1304 goto err;
1305 }
1306
1307 nsvc = gprs_ns2_ip_connect(bind, &remote, nse, nsvci);
1308 if (!nsvc) {
1309 vty_out(vty, "Can not create NS-VC.%s", VTY_NEWLINE);
1310 goto err;
1311 }
1312 nsvc->persistent = true;
1313
1314 return CMD_SUCCESS;
1315
1316err:
1317 if (ll_modified)
1318 nse->ll = GPRS_NS2_LL_UNDEF;
1319 if (dialect_modified)
Harald Welte06d9bf92021-03-05 10:20:11 +01001320 ns2_nse_set_dialect(nse, GPRS_NS2_DIALECT_UNDEF);
Alexander Couzensda1bf8e2021-01-25 16:27:33 +01001321 return CMD_WARNING;
1322}
1323
1324DEFUN(cfg_no_ns_nse_nsvc_ipa, cfg_no_ns_nse_nsvc_ipa_cmd,
1325 "no nsvc ipa BIND " VTY_IPV46_CMD " <1-65535> nsvci <0-65535>",
1326 NO_STR
1327 "Delete a NS Virtual Connection\n"
1328 "NS over UDP\n"
1329 "A unique bind identifier created by ns bind\n"
1330 "Remote IPv4 Address\n" "Remote IPv6 Address\n"
1331 "Remote UDP Port\n"
1332 NSVCI_STR
1333 NSVCI_STR
1334 )
1335{
1336 struct gprs_ns2_vc_bind *bind;
1337 struct gprs_ns2_vc *nsvc;
1338 struct gprs_ns2_nse *nse = vty->index;
1339 const char *bind_name = argv[0];
1340 struct osmo_sockaddr_str remote_str;
1341 struct osmo_sockaddr remote;
1342 uint16_t port = atoi(argv[2]);
1343 uint16_t nsvci = atoi(argv[3]);
1344
1345 if (nse->ll != GPRS_NS2_LL_UDP) {
1346 vty_out(vty, "This NSE doesn't support UDP.%s", VTY_NEWLINE);
1347 return CMD_WARNING;
1348 }
1349
1350 if (nse->dialect != GPRS_NS2_DIALECT_IPACCESS) {
1351 vty_out(vty, "This NSE doesn't support UDP with dialect ipaccess.%s", VTY_NEWLINE);
1352 return CMD_WARNING;
1353 }
1354
1355 bind = gprs_ns2_bind_by_name(vty_nsi, bind_name);
1356 if (!bind) {
1357 vty_out(vty, "Can not find bind with name %s%s",
1358 bind_name, VTY_NEWLINE);
1359 return CMD_WARNING;
1360 }
1361
1362 if (bind->ll != GPRS_NS2_LL_UDP) {
1363 vty_out(vty, "Bind %s is not an UDP bind.%s",
1364 bind_name, VTY_NEWLINE);
1365 return CMD_WARNING;
1366 }
1367
1368 if (osmo_sockaddr_str_from_str(&remote_str, argv[1], port)) {
1369 vty_out(vty, "Can not parse IPv4/IPv6 or port.%s", VTY_NEWLINE);
1370 return CMD_WARNING;
1371 }
1372
1373 if (osmo_sockaddr_str_to_sockaddr(&remote_str, &remote.u.sas)) {
1374 vty_out(vty, "Can not parse IPv4/IPv6 or port.%s", VTY_NEWLINE);
1375 return CMD_WARNING;
1376 }
1377
1378 nsvc = gprs_ns2_nsvc_by_sockaddr_bind(bind, &remote);
1379 if (!nsvc) {
1380 vty_out(vty, "Can not find NS-VC with remote %s:%u%s",
1381 remote_str.ip, remote_str.port, VTY_NEWLINE);
1382 return CMD_WARNING;
1383 }
1384
1385 if (!nsvc->persistent) {
1386 vty_out(vty, "NS-VC with remote %s:%u is a dynamic NS-VC. Not configured by vty.%s",
1387 remote_str.ip, remote_str.port, VTY_NEWLINE);
1388 return CMD_WARNING;
1389 }
1390
1391 if (nsvc->nse != nse) {
1392 vty_out(vty, "NS-VC is not part of this NSE!%s", VTY_NEWLINE);
1393 return CMD_WARNING;
1394 }
1395
1396 if (!nsvc->nsvci_is_valid) {
1397 vty_out(vty, "NS-VC doesn't have a nsvci!%s", VTY_NEWLINE);
1398 return CMD_WARNING;
1399 }
1400
1401 if (nsvc->nsvci != nsvci) {
1402 vty_out(vty, "NS-VC has a different nsvci (%u)!%s",
1403 nsvc->nsvci, VTY_NEWLINE);
1404 return CMD_WARNING;
1405 }
1406
1407 gprs_ns2_free_nsvc(nsvc);
1408 if (llist_empty(&nse->nsvc)) {
1409 nse->ll = GPRS_NS2_LL_UNDEF;
Harald Welte06d9bf92021-03-05 10:20:11 +01001410 ns2_nse_set_dialect(nse, GPRS_NS2_DIALECT_UNDEF);
Alexander Couzensda1bf8e2021-01-25 16:27:33 +01001411 }
1412
1413 return CMD_SUCCESS;
1414}
1415
Alexander Couzens5fa431c2021-02-08 23:21:54 +01001416DEFUN(cfg_ns_nse_ip_sns_remote, cfg_ns_nse_ip_sns_remote_cmd,
1417 "ip-sns-remote " VTY_IPV46_CMD " <1-65535>",
Alexander Couzensda1bf8e2021-01-25 16:27:33 +01001418 "SNS Initial Endpoint\n"
1419 "SGSN IPv4 Address\n" "SGSN IPv6 Address\n"
1420 "SGSN UDP Port\n"
1421 )
1422{
1423 struct gprs_ns2_nse *nse = vty->index;
1424 bool dialect_modified = false;
1425 bool ll_modified = false;
1426 int rc;
1427
1428 /* argv[0] */
1429 struct osmo_sockaddr_str remote_str;
1430 struct osmo_sockaddr remote;
1431 uint16_t port = atoi(argv[1]);
1432
1433 if (nse->ll == GPRS_NS2_LL_UNDEF) {
1434 nse->ll = GPRS_NS2_LL_UDP;
1435 ll_modified = true;
1436 }
1437
1438 if (nse->dialect == GPRS_NS2_DIALECT_UNDEF) {
Harald Welte06d9bf92021-03-05 10:20:11 +01001439 if (ns2_nse_set_dialect(nse, GPRS_NS2_DIALECT_SNS) < 0)
Alexander Couzensda1bf8e2021-01-25 16:27:33 +01001440 goto err;
Alexander Couzensda1bf8e2021-01-25 16:27:33 +01001441 dialect_modified = true;
1442 }
1443
1444 if (nse->ll != GPRS_NS2_LL_UDP) {
1445 vty_out(vty, "Can not mix NS-VC with different link layer%s", VTY_NEWLINE);
1446 goto err;
1447 }
1448
1449 if (nse->dialect != GPRS_NS2_DIALECT_SNS) {
1450 vty_out(vty, "Can not mix NS-VC with different dialects%s", VTY_NEWLINE);
1451 goto err;
1452 }
1453
1454 if (osmo_sockaddr_str_from_str(&remote_str, argv[0], port)) {
1455 vty_out(vty, "Can not parse IPv4/IPv6 or port.%s", VTY_NEWLINE);
1456 goto err;
1457 }
1458
1459 if (osmo_sockaddr_str_to_sockaddr(&remote_str, &remote.u.sas)) {
1460 vty_out(vty, "Can not parse IPv4/IPv6 or port.%s", VTY_NEWLINE);
1461 goto err;
1462 }
1463
1464 rc = gprs_ns2_sns_add_endpoint(nse, &remote);
1465 switch (rc) {
1466 case 0:
1467 return CMD_SUCCESS;
1468 case -EADDRINUSE:
1469 vty_out(vty, "Specified SNS endpoint already part of the NSE.%s", VTY_NEWLINE);
1470 return CMD_WARNING;
1471 default:
1472 vty_out(vty, "Can not add specified SNS endpoint.%s", VTY_NEWLINE);
1473 return CMD_WARNING;
1474 }
1475
1476err:
1477 if (ll_modified)
1478 nse->ll = GPRS_NS2_LL_UNDEF;
1479 if (dialect_modified)
Harald Welte06d9bf92021-03-05 10:20:11 +01001480 ns2_nse_set_dialect(nse, GPRS_NS2_DIALECT_UNDEF);
Alexander Couzensda1bf8e2021-01-25 16:27:33 +01001481 return CMD_WARNING;
1482}
1483
Alexander Couzens5fa431c2021-02-08 23:21:54 +01001484DEFUN(cfg_no_ns_nse_ip_sns_remote, cfg_no_ns_nse_ip_sns_remote_cmd,
1485 "no ip-sns-remote " VTY_IPV46_CMD " <1-65535>",
Alexander Couzensda1bf8e2021-01-25 16:27:33 +01001486 NO_STR
1487 "Delete a SNS Initial Endpoint\n"
1488 "SGSN IPv4 Address\n" "SGSN IPv6 Address\n"
1489 "SGSN UDP Port\n"
1490 )
1491{
1492 struct gprs_ns2_nse *nse = vty->index;
1493 struct osmo_sockaddr_str remote_str; /* argv[0] */
1494 struct osmo_sockaddr remote;
1495 uint16_t port = atoi(argv[1]);
Alexander Couzensda1bf8e2021-01-25 16:27:33 +01001496
1497 if (nse->ll != GPRS_NS2_LL_UDP) {
1498 vty_out(vty, "This NSE doesn't support UDP.%s", VTY_NEWLINE);
1499 return CMD_WARNING;
1500 }
1501
1502 if (nse->dialect != GPRS_NS2_DIALECT_SNS) {
1503 vty_out(vty, "This NSE doesn't support UDP with dialect ip-sns.%s", VTY_NEWLINE);
1504 return CMD_WARNING;
1505 }
1506
1507 if (osmo_sockaddr_str_from_str(&remote_str, argv[0], port)) {
1508 vty_out(vty, "Can not parse IPv4/IPv6 or port.%s", VTY_NEWLINE);
1509 return CMD_WARNING;
1510 }
1511
1512 if (osmo_sockaddr_str_to_sockaddr(&remote_str, &remote.u.sas)) {
1513 vty_out(vty, "Can not parse IPv4/IPv6 or port.%s", VTY_NEWLINE);
1514 return CMD_WARNING;
1515 }
1516
1517 if (gprs_ns2_sns_del_endpoint(nse, &remote)) {
1518 vty_out(vty, "Can not remove specified SNS endpoint.%s", VTY_NEWLINE);
1519 return CMD_WARNING;
1520 }
1521
Alexander Couzens6b9d2322021-02-12 03:17:59 +01001522 if (vty_nse_check_sns(nse)) {
1523 /* there is still sns configuration valid */
Alexander Couzensda1bf8e2021-01-25 16:27:33 +01001524 return CMD_SUCCESS;
Alexander Couzensda1bf8e2021-01-25 16:27:33 +01001525 } else {
1526 /* clean up nse to allow other nsvc commands */
Harald Welte06d9bf92021-03-05 10:20:11 +01001527 ns2_nse_set_dialect(nse, GPRS_NS2_DIALECT_UNDEF);
Alexander Couzensda1bf8e2021-01-25 16:27:33 +01001528 nse->ll = GPRS_NS2_LL_UNDEF;
Alexander Couzensda1bf8e2021-01-25 16:27:33 +01001529 }
1530
1531 return CMD_SUCCESS;
1532}
1533
Alexander Couzens6b9d2322021-02-12 03:17:59 +01001534DEFUN(cfg_ns_nse_ip_sns_bind, cfg_ns_nse_ip_sns_bind_cmd,
1535 "ip-sns-bind BINDID",
1536 "IP SNS binds\n"
Harald Welte2230a912021-03-04 20:09:50 +01001537 "Name of NS udp bind whose IP endpoint will be used as IP-SNS local endpoint. Can be given multiple times.\n")
Alexander Couzens6b9d2322021-02-12 03:17:59 +01001538{
1539 struct gprs_ns2_nse *nse = vty->index;
1540 struct gprs_ns2_vc_bind *bind;
1541 struct vty_bind *vbind;
1542 struct vty_nse *vnse;
1543 const char *name = argv[0];
1544 bool ll_modified = false;
1545 bool dialect_modified = false;
1546 int rc;
1547
1548 if (nse->ll == GPRS_NS2_LL_UNDEF) {
1549 nse->ll = GPRS_NS2_LL_UDP;
1550 ll_modified = true;
1551 }
1552
1553 if (nse->dialect == GPRS_NS2_DIALECT_UNDEF) {
Harald Welte06d9bf92021-03-05 10:20:11 +01001554 if (ns2_nse_set_dialect(nse, GPRS_NS2_DIALECT_SNS) < 0)
Alexander Couzens6b9d2322021-02-12 03:17:59 +01001555 goto err;
Alexander Couzens6b9d2322021-02-12 03:17:59 +01001556 dialect_modified = true;
1557 }
1558
1559 if (nse->ll != GPRS_NS2_LL_UDP) {
1560 vty_out(vty, "Can not mix NS-VC with different link layer%s", VTY_NEWLINE);
1561 goto err;
1562 }
1563
1564 if (nse->dialect != GPRS_NS2_DIALECT_SNS) {
1565 vty_out(vty, "Can not mix NS-VC with different dialects%s", VTY_NEWLINE);
1566 goto err;
1567 }
1568
1569 vbind = vty_bind_by_name(name);
1570 if (!vbind) {
1571 vty_out(vty, "Can not find the given bind '%s'%s", name, VTY_NEWLINE);
1572 goto err;
1573 }
1574
1575 if (vbind->ll != GPRS_NS2_LL_UDP) {
1576 vty_out(vty, "ip-sns-bind can only be used with UDP bind%s",
1577 VTY_NEWLINE);
1578 goto err;
1579 }
1580
1581 /* the vnse has been created together when creating the nse node. The parent node should check this already! */
1582 vnse = vty_nse_by_nsei(nse->nsei);
1583 OSMO_ASSERT(vnse);
1584
1585 rc = vty_nse_add_vbind(vnse, vbind);
1586 switch (rc) {
1587 case 0:
1588 break;
1589 case -EALREADY:
1590 vty_out(vty, "Failed to add ip-sns-bind %s already present%s", name, VTY_NEWLINE);
1591 goto err;
1592 case -ENOMEM:
1593 vty_out(vty, "Failed to add ip-sns-bind %s out of memory%s", name, VTY_NEWLINE);
1594 goto err;
1595 default:
1596 vty_out(vty, "Failed to add ip-sns-bind %s! %d%s", name, rc, VTY_NEWLINE);
1597 goto err;
1598 }
1599
1600 /* the bind might not yet created because "listen" is missing. */
1601 bind = gprs_ns2_bind_by_name(vty_nsi, name);
1602 if (!bind)
1603 return CMD_SUCCESS;
1604
1605 rc = gprs_ns2_sns_add_bind(nse, bind);
1606 switch (rc) {
1607 case 0:
1608 break;
1609 case -EALREADY:
1610 vty_out(vty, "Failed to add ip-sns-bind %s already present%s", name, VTY_NEWLINE);
1611 goto err;
1612 case -ENOMEM:
1613 vty_out(vty, "Failed to add ip-sns-bind %s out of memory%s", name, VTY_NEWLINE);
1614 goto err;
1615 default:
1616 vty_out(vty, "Failed to add ip-sns-bind %s! %d%s", name, rc, VTY_NEWLINE);
1617 goto err;
1618 }
1619
1620 return CMD_SUCCESS;
1621err:
1622 if (ll_modified)
1623 nse->ll = GPRS_NS2_LL_UNDEF;
1624 if (dialect_modified)
Harald Welte06d9bf92021-03-05 10:20:11 +01001625 ns2_nse_set_dialect(nse, GPRS_NS2_DIALECT_UNDEF);
Alexander Couzens6b9d2322021-02-12 03:17:59 +01001626
1627 return CMD_WARNING;
1628}
1629
1630DEFUN(cfg_no_ns_nse_ip_sns_bind, cfg_no_ns_nse_ip_sns_bind_cmd,
1631 "no ip-sns-bind BINDID",
1632 NO_STR
1633 "IP SNS binds\n"
Harald Welte2230a912021-03-04 20:09:50 +01001634 "Name of NS udp bind whose IP endpoint will not be used as IP-SNS local endpoint\n")
Alexander Couzens6b9d2322021-02-12 03:17:59 +01001635{
1636 struct gprs_ns2_nse *nse = vty->index;
1637 struct gprs_ns2_vc_bind *bind;
1638 struct vty_bind *vbind;
1639 struct vty_nse *vnse;
1640 const char *name = argv[0];
1641 int rc;
1642
1643 if (nse->ll != GPRS_NS2_LL_UDP) {
1644 vty_out(vty, "This NSE doesn't support UDP.%s", VTY_NEWLINE);
1645 return CMD_WARNING;
1646 }
1647
1648 if (nse->dialect != GPRS_NS2_DIALECT_SNS) {
1649 vty_out(vty, "This NSE doesn't support UDP with dialect ip-sns.%s", VTY_NEWLINE);
1650 return CMD_WARNING;
1651 }
1652
1653 vbind = vty_bind_by_name(name);
1654 if (!vbind) {
1655 vty_out(vty, "Can not find the given bind '%s'%s", name, VTY_NEWLINE);
1656 return CMD_WARNING;
1657 }
1658
1659 if (vbind->ll != GPRS_NS2_LL_UDP) {
1660 vty_out(vty, "no ip-sns-bind can only be used with UDP bind%s",
1661 VTY_NEWLINE);
1662 return CMD_WARNING;
1663 }
1664
1665 /* the vnse has been created together when creating the nse node. The parent node should check this already! */
1666 vnse = vty_nse_by_nsei(nse->nsei);
1667 OSMO_ASSERT(vnse);
1668
1669 rc = vty_nse_remove_vbind(vnse, vbind);
1670 switch(rc) {
1671 case 0:
1672 break;
1673 case -ENOENT:
1674 vty_out(vty, "Bind %s is not part of this NSE%s", name, VTY_NEWLINE);
1675 return CMD_WARNING;
1676 case -EINVAL:
1677 vty_out(vty, "no ip-sns-bind can only be used with UDP bind%s",
1678 VTY_NEWLINE);
1679 return CMD_WARNING;
1680 default:
1681 return CMD_WARNING;
1682 }
1683
1684 /* the bind might not exists yet */
1685 bind = gprs_ns2_bind_by_name(vty_nsi, name);
1686 if (bind)
1687 gprs_ns2_sns_del_bind(nse, bind);
1688
1689 if (!vty_nse_check_sns(nse)) {
1690 /* clean up nse to allow other nsvc commands */
Harald Welte06d9bf92021-03-05 10:20:11 +01001691 ns2_nse_set_dialect(nse, GPRS_NS2_DIALECT_UNDEF);
Alexander Couzens6b9d2322021-02-12 03:17:59 +01001692 nse->ll = GPRS_NS2_LL_UNDEF;
Alexander Couzens6b9d2322021-02-12 03:17:59 +01001693 }
1694
1695 return CMD_SUCCESS;
1696}
Alexander Couzensda1bf8e2021-01-25 16:27:33 +01001697
1698/* non-config commands */
Alexander Couzens6a161492020-07-12 13:45:50 +02001699static void dump_nsvc(struct vty *vty, struct gprs_ns2_vc *nsvc, bool stats)
1700{
Harald Weltedc2d0802020-12-01 18:17:28 +01001701 char nsvci_str[32];
1702
1703 if (nsvc->nsvci_is_valid)
1704 snprintf(nsvci_str, sizeof(nsvci_str), "%05u", nsvc->nsvci);
1705 else
1706 snprintf(nsvci_str, sizeof(nsvci_str), "none");
1707
1708 vty_out(vty, " NSVCI %s: %s %s data_weight=%u sig_weight=%u %s%s", nsvci_str,
1709 osmo_fsm_inst_state_name(nsvc->fi),
1710 nsvc->persistent ? "PERSIST" : "DYNAMIC",
1711 nsvc->data_weight, nsvc->sig_weight,
1712 gprs_ns2_ll_str(nsvc), VTY_NEWLINE);
Alexander Couzens6a161492020-07-12 13:45:50 +02001713
1714 if (stats) {
Harald Welte7aa60992020-12-01 17:53:17 +01001715 vty_out_rate_ctr_group(vty, " ", nsvc->ctrg);
1716 vty_out_stat_item_group(vty, " ", nsvc->statg);
Alexander Couzens6a161492020-07-12 13:45:50 +02001717 }
1718}
1719
1720static void dump_nse(struct vty *vty, const struct gprs_ns2_nse *nse, bool stats, bool persistent_only)
1721{
1722 struct gprs_ns2_vc *nsvc;
1723
Harald Welte0ff12ad2020-12-01 17:51:07 +01001724 vty_out(vty, "NSEI %05u: %s, %s%s", nse->nsei, gprs_ns2_lltype_str(nse->ll),
1725 nse->alive ? "ALIVE" : "DEAD", VTY_NEWLINE);
Alexander Couzens6a161492020-07-12 13:45:50 +02001726
Alexander Couzens8dfc24c2021-01-25 16:09:23 +01001727 ns2_sns_dump_vty(vty, " ", nse, stats);
Alexander Couzens6a161492020-07-12 13:45:50 +02001728 llist_for_each_entry(nsvc, &nse->nsvc, list) {
1729 if (persistent_only) {
1730 if (nsvc->persistent)
1731 dump_nsvc(vty, nsvc, stats);
1732 } else {
1733 dump_nsvc(vty, nsvc, stats);
1734 }
1735 }
1736}
1737
Alexander Couzens22f34712020-10-02 02:34:39 +02001738static void dump_bind(struct vty *vty, const struct gprs_ns2_vc_bind *bind, bool stats)
1739{
1740 if (bind->dump_vty)
1741 bind->dump_vty(bind, vty, stats);
Harald Welte76346072021-01-31 11:54:02 +01001742
1743 if (stats) {
1744 vty_out_stat_item_group(vty, " ", bind->statg);
1745 }
Alexander Couzens22f34712020-10-02 02:34:39 +02001746}
1747
Harald Welte2fce19a2020-12-01 17:52:55 +01001748static void dump_ns_bind(struct vty *vty, const struct gprs_ns2_inst *nsi, bool stats)
Alexander Couzens6a161492020-07-12 13:45:50 +02001749{
Alexander Couzens22f34712020-10-02 02:34:39 +02001750 struct gprs_ns2_vc_bind *bind;
Alexander Couzens6a161492020-07-12 13:45:50 +02001751
Alexander Couzens22f34712020-10-02 02:34:39 +02001752 llist_for_each_entry(bind, &nsi->binding, list) {
1753 dump_bind(vty, bind, stats);
1754 }
Harald Welte2fce19a2020-12-01 17:52:55 +01001755}
1756
1757
1758static void dump_ns_entities(struct vty *vty, const struct gprs_ns2_inst *nsi, bool stats, bool persistent_only)
1759{
1760 struct gprs_ns2_nse *nse;
Alexander Couzens22f34712020-10-02 02:34:39 +02001761
Alexander Couzens6a161492020-07-12 13:45:50 +02001762 llist_for_each_entry(nse, &nsi->nse, list) {
1763 dump_nse(vty, nse, stats, persistent_only);
Alexander Couzens6a161492020-07-12 13:45:50 +02001764 }
Alexander Couzens6a161492020-07-12 13:45:50 +02001765}
1766
Harald Welte25ee7552020-12-02 22:14:00 +01001767/* Backwards compatibility, among other things for the TestVTYGbproxy which expects
1768 * 'show ns' to output something about binds */
1769DEFUN_HIDDEN(show_ns, show_ns_cmd, "show ns",
1770 SHOW_STR SHOW_NS_STR)
1771{
1772 dump_ns_entities(vty, vty_nsi, false, false);
1773 dump_ns_bind(vty, vty_nsi, false);
1774 return CMD_SUCCESS;
1775}
1776
1777
Harald Welte2fce19a2020-12-01 17:52:55 +01001778DEFUN(show_ns_binds, show_ns_binds_cmd, "show ns binds [stats]",
Daniel Willmanncb3e9b52020-12-02 15:50:22 +01001779 SHOW_STR SHOW_NS_STR
Harald Welte2fce19a2020-12-01 17:52:55 +01001780 "Display information about the NS protocol binds\n"
1781 "Include statistic\n")
Alexander Couzens6a161492020-07-12 13:45:50 +02001782{
Harald Welte2fce19a2020-12-01 17:52:55 +01001783 bool stats = false;
1784 if (argc > 0)
1785 stats = true;
1786
1787 dump_ns_bind(vty, vty_nsi, stats);
Alexander Couzens6a161492020-07-12 13:45:50 +02001788 return CMD_SUCCESS;
1789}
1790
Harald Welte2fce19a2020-12-01 17:52:55 +01001791DEFUN(show_ns_entities, show_ns_entities_cmd, "show ns entities [stats]",
Daniel Willmanncb3e9b52020-12-02 15:50:22 +01001792 SHOW_STR SHOW_NS_STR
Harald Welte2fce19a2020-12-01 17:52:55 +01001793 "Display information about the NS protocol entities (NSEs)\n"
Alexander Couzens6a161492020-07-12 13:45:50 +02001794 "Include statistics\n")
1795{
Harald Welte2fce19a2020-12-01 17:52:55 +01001796 bool stats = false;
1797 if (argc > 0)
1798 stats = true;
1799
1800 dump_ns_entities(vty, vty_nsi, stats, false);
Alexander Couzens6a161492020-07-12 13:45:50 +02001801 return CMD_SUCCESS;
1802}
1803
1804DEFUN(show_ns_pers, show_ns_pers_cmd, "show ns persistent",
Daniel Willmanncb3e9b52020-12-02 15:50:22 +01001805 SHOW_STR SHOW_NS_STR
Alexander Couzens6a161492020-07-12 13:45:50 +02001806 "Show only persistent NS\n")
1807{
Harald Welte2fce19a2020-12-01 17:52:55 +01001808 dump_ns_entities(vty, vty_nsi, true, true);
Alexander Couzens6a161492020-07-12 13:45:50 +02001809 return CMD_SUCCESS;
1810}
1811
1812DEFUN(show_nse, show_nse_cmd, "show ns (nsei|nsvc) <0-65535> [stats]",
Daniel Willmanncb3e9b52020-12-02 15:50:22 +01001813 SHOW_STR SHOW_NS_STR
Alexander Couzens6a161492020-07-12 13:45:50 +02001814 "Select one NSE by its NSE Identifier\n"
1815 "Select one NSE by its NS-VC Identifier\n"
1816 "The Identifier of selected type\n"
1817 "Include Statistics\n")
1818{
1819 struct gprs_ns2_inst *nsi = vty_nsi;
1820 struct gprs_ns2_nse *nse;
1821 struct gprs_ns2_vc *nsvc;
1822 uint16_t id = atoi(argv[1]);
1823 bool show_stats = false;
1824
1825 if (argc >= 3)
1826 show_stats = true;
1827
1828 if (!strcmp(argv[0], "nsei")) {
1829 nse = gprs_ns2_nse_by_nsei(nsi, id);
1830 if (!nse) {
1831 return CMD_WARNING;
1832 }
1833
1834 dump_nse(vty, nse, show_stats, false);
1835 } else {
1836 nsvc = gprs_ns2_nsvc_by_nsvci(nsi, id);
1837
1838 if (!nsvc) {
1839 vty_out(vty, "No such NS Entity%s", VTY_NEWLINE);
1840 return CMD_WARNING;
1841 }
1842
1843 dump_nsvc(vty, nsvc, show_stats);
1844 }
1845
1846 return CMD_SUCCESS;
1847}
1848
Daniel Willmanndbab7142020-11-18 14:19:56 +01001849static int nsvc_force_unconf_cb(struct gprs_ns2_vc *nsvc, void *ctx)
1850{
Alexander Couzens8dfc24c2021-01-25 16:09:23 +01001851 ns2_vc_force_unconfigured(nsvc);
Harald Welte7fe8d712021-01-31 18:40:54 +01001852 ns2_vc_fsm_start(nsvc);
Daniel Willmanndbab7142020-11-18 14:19:56 +01001853 return 0;
1854}
1855
1856DEFUN_HIDDEN(nsvc_force_unconf, nsvc_force_unconf_cmd,
1857 "nsvc nsei <0-65535> force-unconfigured",
1858 "NS Virtual Connection\n"
1859 "The NSEI\n"
1860 "Reset the NSVCs back to initial state\n"
1861 )
1862{
1863 struct gprs_ns2_inst *nsi = vty_nsi;
1864 struct gprs_ns2_nse *nse;
1865
1866 uint16_t id = atoi(argv[0]);
1867
1868 nse = gprs_ns2_nse_by_nsei(nsi, id);
1869 if (!nse) {
1870 vty_out(vty, "Could not find NSE for NSEI %u%s", id, VTY_NEWLINE);
1871 return CMD_WARNING;
1872 }
1873
Alexander Couzensda1bf8e2021-01-25 16:27:33 +01001874 if (!nse->persistent) {
1875 gprs_ns2_free_nse(nse);
1876 } else if (nse->dialect == GPRS_NS2_DIALECT_SNS) {
Alexander Couzens280ed782020-12-21 18:25:41 +01001877 gprs_ns2_free_nsvcs(nse);
1878 } else {
1879 /* Perform the operation for all nsvc */
1880 gprs_ns2_nse_foreach_nsvc(nse, nsvc_force_unconf_cb, NULL);
1881 }
Daniel Willmanndbab7142020-11-18 14:19:56 +01001882
1883 return CMD_SUCCESS;
1884}
1885
Alexander Couzensda1bf8e2021-01-25 16:27:33 +01001886DEFUN(nsvc_block, nsvc_block_cmd,
1887 "nsvc <0-65535> (block|unblock)",
1888 "NS Virtual Connection\n"
1889 NSVCI_STR
1890 "Block a NSVC. As cause code O&M intervention will be used.\n"
1891 "Unblock a NSVC. As cause code O&M intervention will be used.\n")
Alexander Couzens841817e2020-11-19 00:41:29 +01001892{
Alexander Couzensda1bf8e2021-01-25 16:27:33 +01001893 struct gprs_ns2_inst *nsi = vty_nsi;
1894 struct gprs_ns2_vc *nsvc;
Alexander Couzens841817e2020-11-19 00:41:29 +01001895
Alexander Couzensda1bf8e2021-01-25 16:27:33 +01001896 uint16_t id = atoi(argv[0]);
Alexander Couzens841817e2020-11-19 00:41:29 +01001897
Alexander Couzensda1bf8e2021-01-25 16:27:33 +01001898 nsvc = gprs_ns2_nsvc_by_nsvci(nsi, id);
1899 if (!nsvc) {
1900 vty_out(vty, "Could not find NSVCI %05u%s", id, VTY_NEWLINE);
Alexander Couzens841817e2020-11-19 00:41:29 +01001901 return CMD_WARNING;
1902 }
1903
Alexander Couzensda1bf8e2021-01-25 16:27:33 +01001904 if (!strcmp(argv[1], "block")) {
1905 ns2_vc_block(nsvc);
1906 } else {
1907 ns2_vc_unblock(nsvc);
Alexander Couzens6a161492020-07-12 13:45:50 +02001908 }
1909
1910 return CMD_SUCCESS;
1911}
1912
Alexander Couzensda1bf8e2021-01-25 16:27:33 +01001913static void log_set_nse_filter(struct log_target *target,
1914 struct gprs_ns2_nse *nse)
Alexander Couzens6a161492020-07-12 13:45:50 +02001915{
Alexander Couzensda1bf8e2021-01-25 16:27:33 +01001916 if (nse) {
1917 target->filter_map |= (1 << LOG_FLT_GB_NSE);
1918 target->filter_data[LOG_FLT_GB_NSE] = nse;
1919 } else if (target->filter_data[LOG_FLT_GB_NSE]) {
1920 target->filter_map = ~(1 << LOG_FLT_GB_NSE);
1921 target->filter_data[LOG_FLT_GB_NSE] = NULL;
1922 }
Alexander Couzens6a161492020-07-12 13:45:50 +02001923}
1924
Alexander Couzensda1bf8e2021-01-25 16:27:33 +01001925static void log_set_nsvc_filter(struct log_target *target,
1926 struct gprs_ns2_vc *nsvc)
Alexander Couzens6a161492020-07-12 13:45:50 +02001927{
Alexander Couzensda1bf8e2021-01-25 16:27:33 +01001928 if (nsvc) {
1929 target->filter_map |= (1 << LOG_FLT_GB_NSVC);
1930 target->filter_data[LOG_FLT_GB_NSVC] = nsvc;
1931 } else if (target->filter_data[LOG_FLT_GB_NSVC]) {
1932 target->filter_map = ~(1 << LOG_FLT_GB_NSVC);
1933 target->filter_data[LOG_FLT_GB_NSVC] = NULL;
1934 }
Alexander Couzens6a161492020-07-12 13:45:50 +02001935}
1936
Daniel Willmann751977b2020-12-02 18:59:44 +01001937DEFUN(logging_fltr_nse,
1938 logging_fltr_nse_cmd,
1939 "logging filter nse nsei <0-65535>",
1940 LOGGING_STR FILTER_STR
1941 "Filter based on NS Entity\n"
1942 "Identify NSE by NSEI\n"
1943 "Numeric identifier\n")
1944{
1945 struct log_target *tgt;
1946 struct gprs_ns2_nse *nse;
Daniel Willmann89106522020-12-04 01:36:59 +01001947 uint16_t id = atoi(argv[0]);
Daniel Willmann751977b2020-12-02 18:59:44 +01001948
1949 log_tgt_mutex_lock();
1950 tgt = osmo_log_vty2tgt(vty);
1951 if (!tgt) {
1952 log_tgt_mutex_unlock();
1953 return CMD_WARNING;
1954 }
1955
1956 nse = gprs_ns2_nse_by_nsei(vty_nsi, id);
1957 if (!nse) {
1958 vty_out(vty, "No NSE by that identifier%s", VTY_NEWLINE);
1959 log_tgt_mutex_unlock();
1960 return CMD_WARNING;
1961 }
1962
1963 log_set_nse_filter(tgt, nse);
1964 log_tgt_mutex_unlock();
1965 return CMD_SUCCESS;
1966}
1967
Alexander Couzens6a161492020-07-12 13:45:50 +02001968/* TODO: add filter for single connection by description */
1969DEFUN(logging_fltr_nsvc,
1970 logging_fltr_nsvc_cmd,
1971 "logging filter nsvc nsvci <0-65535>",
1972 LOGGING_STR FILTER_STR
1973 "Filter based on NS Virtual Connection\n"
1974 "Identify NS-VC by NSVCI\n"
1975 "Numeric identifier\n")
1976{
1977 struct log_target *tgt;
1978 struct gprs_ns2_vc *nsvc;
Daniel Willmann89106522020-12-04 01:36:59 +01001979 uint16_t id = atoi(argv[0]);
Alexander Couzens6a161492020-07-12 13:45:50 +02001980
1981 log_tgt_mutex_lock();
1982 tgt = osmo_log_vty2tgt(vty);
1983 if (!tgt) {
1984 log_tgt_mutex_unlock();
1985 return CMD_WARNING;
1986 }
1987
1988 nsvc = gprs_ns2_nsvc_by_nsvci(vty_nsi, id);
1989 if (!nsvc) {
1990 vty_out(vty, "No NS-VC by that identifier%s", VTY_NEWLINE);
1991 log_tgt_mutex_unlock();
1992 return CMD_WARNING;
1993 }
1994
1995 log_set_nsvc_filter(tgt, nsvc);
1996 log_tgt_mutex_unlock();
1997 return CMD_SUCCESS;
1998}
1999
Alexander Couzense43b46e2021-01-27 21:52:08 +01002000/*! initialized a reduced vty interface which excludes the configuration nodes besides timeouts.
2001 * This can be used by the PCU which can be only configured by the BTS/BSC and not by the vty.
2002 * \param[in] nsi NS instance on which we operate
2003 * \return 0 on success.
2004 */
2005int gprs_ns2_vty_init_reduced(struct gprs_ns2_inst *nsi)
Alexander Couzens6a161492020-07-12 13:45:50 +02002006{
Pau Espin Pedrolcaf53172021-01-28 13:37:50 +01002007 vty_nsi = nsi;
Alexander Couzensda1bf8e2021-01-25 16:27:33 +01002008 INIT_LLIST_HEAD(&binds);
Alexander Couzens6b9d2322021-02-12 03:17:59 +01002009 INIT_LLIST_HEAD(&nses);
Pau Espin Pedrolcaf53172021-01-28 13:37:50 +01002010
Alexander Couzensda1bf8e2021-01-25 16:27:33 +01002011 vty_fr_network = osmo_fr_network_alloc(nsi);
2012 if (!vty_fr_network)
2013 return -ENOMEM;
Alexander Couzens6a161492020-07-12 13:45:50 +02002014
Harald Welte25ee7552020-12-02 22:14:00 +01002015 install_lib_element_ve(&show_ns_cmd);
Harald Welte2fce19a2020-12-01 17:52:55 +01002016 install_lib_element_ve(&show_ns_binds_cmd);
2017 install_lib_element_ve(&show_ns_entities_cmd);
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +07002018 install_lib_element_ve(&show_ns_pers_cmd);
2019 install_lib_element_ve(&show_nse_cmd);
Daniel Willmann751977b2020-12-02 18:59:44 +01002020 install_lib_element_ve(&logging_fltr_nse_cmd);
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +07002021 install_lib_element_ve(&logging_fltr_nsvc_cmd);
Alexander Couzens6a161492020-07-12 13:45:50 +02002022
Daniel Willmanndbab7142020-11-18 14:19:56 +01002023 install_lib_element(ENABLE_NODE, &nsvc_force_unconf_cmd);
Alexander Couzensda1bf8e2021-01-25 16:27:33 +01002024 install_lib_element(ENABLE_NODE, &nsvc_block_cmd);
Daniel Willmanndbab7142020-11-18 14:19:56 +01002025
Daniel Willmann751977b2020-12-02 18:59:44 +01002026 install_lib_element(CFG_LOG_NODE, &logging_fltr_nse_cmd);
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +07002027 install_lib_element(CFG_LOG_NODE, &logging_fltr_nsvc_cmd);
Alexander Couzens6a161492020-07-12 13:45:50 +02002028
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +07002029 install_lib_element(CONFIG_NODE, &cfg_ns_cmd);
Alexander Couzensda1bf8e2021-01-25 16:27:33 +01002030
Alexander Couzens6a161492020-07-12 13:45:50 +02002031 install_node(&ns_node, config_write_ns);
Alexander Couzensda1bf8e2021-01-25 16:27:33 +01002032 /* TODO: convert into osmo timer */
Vadim Yanitskiy8e7c4962020-10-04 15:37:31 +07002033 install_lib_element(L_NS_NODE, &cfg_ns_timer_cmd);
Alexander Couzense43b46e2021-01-27 21:52:08 +01002034
2035 return 0;
2036}
2037
2038int gprs_ns2_vty_init(struct gprs_ns2_inst *nsi)
2039{
2040 int rc = gprs_ns2_vty_init_reduced(nsi);
2041 if (rc)
2042 return rc;
2043
Alexander Couzensda1bf8e2021-01-25 16:27:33 +01002044 install_lib_element(L_NS_NODE, &cfg_ns_nsei_cmd);
2045 install_lib_element(L_NS_NODE, &cfg_no_ns_nsei_cmd);
2046 install_lib_element(L_NS_NODE, &cfg_ns_bind_cmd);
2047 install_lib_element(L_NS_NODE, &cfg_no_ns_bind_cmd);
Alexander Couzens6a161492020-07-12 13:45:50 +02002048
Alexander Couzens260cd522021-01-28 20:31:31 +01002049 install_node(&ns_bind_node, NULL);
Alexander Couzensda1bf8e2021-01-25 16:27:33 +01002050 install_lib_element(L_NS_BIND_NODE, &cfg_ns_bind_listen_cmd);
2051 install_lib_element(L_NS_BIND_NODE, &cfg_no_ns_bind_listen_cmd);
2052 install_lib_element(L_NS_BIND_NODE, &cfg_ns_bind_dscp_cmd);
2053 install_lib_element(L_NS_BIND_NODE, &cfg_no_ns_bind_dscp_cmd);
Alexander Couzensc4704762021-02-08 23:13:12 +01002054 install_lib_element(L_NS_BIND_NODE, &cfg_ns_bind_ip_sns_weight_cmd);
Alexander Couzensda1bf8e2021-01-25 16:27:33 +01002055 install_lib_element(L_NS_BIND_NODE, &cfg_ns_bind_ipaccess_cmd);
2056 install_lib_element(L_NS_BIND_NODE, &cfg_no_ns_bind_ipaccess_cmd);
2057 install_lib_element(L_NS_BIND_NODE, &cfg_ns_bind_fr_cmd);
2058 install_lib_element(L_NS_BIND_NODE, &cfg_no_ns_bind_fr_cmd);
2059 /* TODO: accept-ip-sns when SGSN SNS has been implemented */
Alexander Couzens6a161492020-07-12 13:45:50 +02002060
Alexander Couzens260cd522021-01-28 20:31:31 +01002061 install_node(&ns_nse_node, NULL);
Alexander Couzensda1bf8e2021-01-25 16:27:33 +01002062 install_lib_element(L_NS_NSE_NODE, &cfg_ns_nse_nsvc_fr_cmd);
2063 install_lib_element(L_NS_NSE_NODE, &cfg_no_ns_nse_nsvci_cmd);
2064 install_lib_element(L_NS_NSE_NODE, &cfg_no_ns_nse_nsvc_fr_dlci_cmd);
2065 install_lib_element(L_NS_NSE_NODE, &cfg_ns_nse_nsvc_udp_cmd);
Alexander Couzensbf5d0db2021-02-12 04:04:13 +01002066 install_lib_element(L_NS_NSE_NODE, &cfg_ns_nse_nsvc_udp_weights_cmd);
Alexander Couzensda1bf8e2021-01-25 16:27:33 +01002067 install_lib_element(L_NS_NSE_NODE, &cfg_no_ns_nse_nsvc_udp_cmd);
2068 install_lib_element(L_NS_NSE_NODE, &cfg_ns_nse_nsvc_ipa_cmd);
2069 install_lib_element(L_NS_NSE_NODE, &cfg_no_ns_nse_nsvc_ipa_cmd);
Alexander Couzens5fa431c2021-02-08 23:21:54 +01002070 install_lib_element(L_NS_NSE_NODE, &cfg_ns_nse_ip_sns_remote_cmd);
2071 install_lib_element(L_NS_NSE_NODE, &cfg_no_ns_nse_ip_sns_remote_cmd);
Alexander Couzens6b9d2322021-02-12 03:17:59 +01002072 install_lib_element(L_NS_NSE_NODE, &cfg_ns_nse_ip_sns_bind_cmd);
2073 install_lib_element(L_NS_NSE_NODE, &cfg_no_ns_nse_ip_sns_bind_cmd);
Alexander Couzens6a161492020-07-12 13:45:50 +02002074
2075 return 0;
2076}