2020-07-12 11:45:50 +00:00
|
|
|
/*! \file gprs_ns2_vty.c
|
|
|
|
* VTY interface for our GPRS Networks Service (NS) implementation. */
|
|
|
|
|
|
|
|
/* (C) 2009-2014 by Harald Welte <laforge@gnumonks.org>
|
|
|
|
* (C) 2016-2017 by sysmocom - s.f.m.c. GmbH
|
|
|
|
* (C) 2020 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
|
|
|
|
* Author: Alexander Couzens <lynxis@fe80.eu>
|
|
|
|
*
|
|
|
|
* All Rights Reserved
|
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: GPL-2.0+
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
|
|
|
|
#include <arpa/inet.h>
|
2020-11-18 23:41:29 +00:00
|
|
|
#include <net/if.h>
|
2020-07-12 11:45:50 +00:00
|
|
|
|
|
|
|
#include <osmocom/core/msgb.h>
|
|
|
|
#include <osmocom/core/byteswap.h>
|
2020-11-18 13:19:56 +00:00
|
|
|
#include <osmocom/core/fsm.h>
|
2020-07-12 11:45:50 +00:00
|
|
|
#include <osmocom/core/talloc.h>
|
|
|
|
#include <osmocom/core/select.h>
|
|
|
|
#include <osmocom/core/rate_ctr.h>
|
|
|
|
#include <osmocom/core/socket.h>
|
|
|
|
#include <osmocom/core/sockaddr_str.h>
|
|
|
|
#include <osmocom/core/linuxlist.h>
|
|
|
|
#include <osmocom/core/socket.h>
|
2020-11-18 23:41:29 +00:00
|
|
|
#include <osmocom/gprs/frame_relay.h>
|
2020-07-12 11:45:50 +00:00
|
|
|
#include <osmocom/gprs/gprs_ns2.h>
|
|
|
|
#include <osmocom/gsm/tlv.h>
|
|
|
|
#include <osmocom/vty/vty.h>
|
|
|
|
#include <osmocom/vty/command.h>
|
|
|
|
#include <osmocom/vty/logging.h>
|
|
|
|
#include <osmocom/vty/telnet_interface.h>
|
|
|
|
#include <osmocom/vty/misc.h>
|
|
|
|
|
|
|
|
#include "gprs_ns2_internal.h"
|
|
|
|
|
2020-12-02 14:50:22 +00:00
|
|
|
#define SHOW_NS_STR "Display information about the NS protocol\n"
|
|
|
|
|
2020-07-12 11:45:50 +00:00
|
|
|
struct ns2_vty_priv {
|
|
|
|
/* global listen */
|
|
|
|
struct osmo_sockaddr_str udp;
|
|
|
|
struct osmo_sockaddr_str frgreaddr;
|
|
|
|
int dscp;
|
|
|
|
enum gprs_ns2_vc_mode vc_mode;
|
|
|
|
bool frgre;
|
|
|
|
|
|
|
|
struct llist_head vtyvc;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ns2_vty_vc {
|
|
|
|
struct llist_head list;
|
|
|
|
|
|
|
|
struct osmo_sockaddr_str remote;
|
2020-11-19 01:34:49 +00:00
|
|
|
enum gprs_ns2_ll ll;
|
2020-07-12 11:45:50 +00:00
|
|
|
|
|
|
|
/* old vty code doesnt support multiple NSVCI per NSEI */
|
|
|
|
uint16_t nsei;
|
|
|
|
uint16_t nsvci;
|
|
|
|
uint16_t frdlci;
|
|
|
|
|
2020-11-18 23:41:29 +00:00
|
|
|
struct {
|
|
|
|
enum osmo_fr_role role;
|
|
|
|
} fr;
|
|
|
|
|
|
|
|
char netif[IF_NAMESIZE];
|
|
|
|
|
2020-07-12 11:45:50 +00:00
|
|
|
bool remote_end_is_sgsn;
|
|
|
|
bool configured;
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct gprs_ns2_inst *vty_nsi = NULL;
|
|
|
|
static struct ns2_vty_priv priv;
|
2020-11-18 23:41:29 +00:00
|
|
|
static struct osmo_fr_network *vty_fr_network = NULL;
|
2020-07-12 11:45:50 +00:00
|
|
|
|
|
|
|
/* FIXME: this should go to some common file as it is copied
|
|
|
|
* in vty_interface.c of the BSC */
|
|
|
|
static const struct value_string gprs_ns_timer_strs[] = {
|
|
|
|
{ 0, "tns-block" },
|
|
|
|
{ 1, "tns-block-retries" },
|
|
|
|
{ 2, "tns-reset" },
|
|
|
|
{ 3, "tns-reset-retries" },
|
|
|
|
{ 4, "tns-test" },
|
|
|
|
{ 5, "tns-alive" },
|
|
|
|
{ 6, "tns-alive-retries" },
|
|
|
|
{ 7, "tsns-prov" },
|
2020-12-16 10:59:19 +00:00
|
|
|
{ 8, "tsns-size-retries" },
|
|
|
|
{ 9, "tsns-config-retries" },
|
2020-07-12 11:45:50 +00:00
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
|
2020-12-02 17:59:44 +00:00
|
|
|
static void log_set_nse_filter(struct log_target *target,
|
|
|
|
struct gprs_ns2_nse *nse)
|
|
|
|
{
|
|
|
|
if (nse) {
|
|
|
|
target->filter_map |= (1 << LOG_FLT_GB_NSE);
|
|
|
|
target->filter_data[LOG_FLT_GB_NSE] = nse;
|
|
|
|
} else if (target->filter_data[LOG_FLT_GB_NSE]) {
|
|
|
|
target->filter_map = ~(1 << LOG_FLT_GB_NSE);
|
|
|
|
target->filter_data[LOG_FLT_GB_NSE] = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-12 11:45:50 +00:00
|
|
|
static void log_set_nsvc_filter(struct log_target *target,
|
|
|
|
struct gprs_ns2_vc *nsvc)
|
|
|
|
{
|
|
|
|
if (nsvc) {
|
|
|
|
target->filter_map |= (1 << LOG_FLT_GB_NSVC);
|
|
|
|
target->filter_data[LOG_FLT_GB_NSVC] = nsvc;
|
|
|
|
} else if (target->filter_data[LOG_FLT_GB_NSVC]) {
|
|
|
|
target->filter_map = ~(1 << LOG_FLT_GB_NSVC);
|
|
|
|
target->filter_data[LOG_FLT_GB_NSVC] = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct cmd_node ns_node = {
|
|
|
|
L_NS_NODE,
|
|
|
|
"%s(config-ns)# ",
|
|
|
|
1,
|
|
|
|
};
|
|
|
|
|
2020-11-25 18:33:42 +00:00
|
|
|
static struct ns2_vty_vc *vtyvc_alloc(uint16_t nsei) {
|
2020-07-12 11:45:50 +00:00
|
|
|
struct ns2_vty_vc *vtyvc = talloc_zero(vty_nsi, struct ns2_vty_vc);
|
|
|
|
if (!vtyvc)
|
|
|
|
return vtyvc;
|
|
|
|
|
|
|
|
vtyvc->nsei = nsei;
|
|
|
|
|
|
|
|
llist_add(&vtyvc->list, &priv.vtyvc);
|
|
|
|
|
|
|
|
return vtyvc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ns2_vc_free(struct ns2_vty_vc *vtyvc) {
|
|
|
|
if (!vtyvc)
|
|
|
|
return;
|
|
|
|
|
|
|
|
llist_del(&vtyvc->list);
|
|
|
|
talloc_free(vtyvc);
|
|
|
|
}
|
|
|
|
|
2020-11-25 18:33:42 +00:00
|
|
|
static struct ns2_vty_vc *vtyvc_by_nsei(uint16_t nsei, bool alloc_missing) {
|
2020-07-12 11:45:50 +00:00
|
|
|
struct ns2_vty_vc *vtyvc;
|
2020-09-23 16:22:20 +00:00
|
|
|
|
2020-07-12 11:45:50 +00:00
|
|
|
llist_for_each_entry(vtyvc, &priv.vtyvc, list) {
|
2020-11-25 18:33:42 +00:00
|
|
|
if (vtyvc->nsei == nsei)
|
2020-07-12 11:45:50 +00:00
|
|
|
return vtyvc;
|
|
|
|
}
|
|
|
|
|
2020-09-23 16:22:20 +00:00
|
|
|
if (!alloc_missing)
|
|
|
|
return NULL;
|
2020-07-12 11:45:50 +00:00
|
|
|
|
2020-11-25 18:33:42 +00:00
|
|
|
vtyvc = vtyvc_alloc(nsei);
|
2020-09-23 16:22:20 +00:00
|
|
|
if (!vtyvc)
|
|
|
|
return vtyvc;
|
2020-07-12 11:45:50 +00:00
|
|
|
|
2020-09-23 16:22:20 +00:00
|
|
|
vtyvc->nsei = nsei;
|
|
|
|
return vtyvc;
|
2020-07-12 11:45:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int config_write_ns(struct vty *vty)
|
|
|
|
{
|
|
|
|
struct ns2_vty_vc *vtyvc;
|
|
|
|
unsigned int i;
|
|
|
|
struct osmo_sockaddr_str sockstr;
|
|
|
|
|
|
|
|
vty_out(vty, "ns%s", VTY_NEWLINE);
|
|
|
|
|
|
|
|
/* global configuration must be written first, as some of it may be
|
|
|
|
* relevant when creating the NSE/NSVC later below */
|
|
|
|
|
|
|
|
vty_out(vty, " encapsulation framerelay-gre enabled %u%s",
|
|
|
|
priv.frgre ? 1 : 0, VTY_NEWLINE);
|
|
|
|
|
|
|
|
if (priv.frgre) {
|
|
|
|
if (strlen(priv.frgreaddr.ip)) {
|
|
|
|
vty_out(vty, " encapsulation framerelay-gre local-ip %s%s",
|
|
|
|
sockstr.ip, VTY_NEWLINE);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (strlen(priv.udp.ip)) {
|
|
|
|
vty_out(vty, " encapsulation udp local-ip %s%s",
|
|
|
|
priv.udp.ip, VTY_NEWLINE);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (priv.udp.port)
|
|
|
|
vty_out(vty, " encapsulation udp local-port %u%s",
|
|
|
|
priv.udp.port, VTY_NEWLINE);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (priv.dscp)
|
|
|
|
vty_out(vty, " encapsulation udp dscp %d%s",
|
|
|
|
priv.dscp, VTY_NEWLINE);
|
|
|
|
|
|
|
|
vty_out(vty, " encapsulation udp use-reset-block-unblock %s%s",
|
|
|
|
priv.vc_mode == NS2_VC_MODE_BLOCKRESET ? "enabled" : "disabled", VTY_NEWLINE);
|
|
|
|
|
|
|
|
llist_for_each_entry(vtyvc, &priv.vtyvc, list) {
|
|
|
|
vty_out(vty, " nse %u nsvci %u%s",
|
|
|
|
vtyvc->nsei, vtyvc->nsvci, VTY_NEWLINE);
|
|
|
|
|
2020-11-25 18:33:42 +00:00
|
|
|
vty_out(vty, " nse %u remote-role %s%s",
|
|
|
|
vtyvc->nsei, vtyvc->remote_end_is_sgsn ? "sgsn" : "bss",
|
|
|
|
VTY_NEWLINE);
|
2020-07-12 11:45:50 +00:00
|
|
|
|
|
|
|
switch (vtyvc->ll) {
|
2020-11-19 01:34:49 +00:00
|
|
|
case GPRS_NS2_LL_UDP:
|
2020-11-25 18:33:42 +00:00
|
|
|
vty_out(vty, " nse %u encapsulation udp%s", vtyvc->nsei, VTY_NEWLINE);
|
|
|
|
vty_out(vty, " nse %u remote-ip %s%s",
|
|
|
|
vtyvc->nsei,
|
|
|
|
vtyvc->remote.ip,
|
|
|
|
VTY_NEWLINE);
|
|
|
|
vty_out(vty, " nse %u remote-port %u%s",
|
|
|
|
vtyvc->nsei, vtyvc->remote.port,
|
2020-07-12 11:45:50 +00:00
|
|
|
VTY_NEWLINE);
|
|
|
|
break;
|
2020-11-19 01:34:49 +00:00
|
|
|
case GPRS_NS2_LL_FR_GRE:
|
2020-11-25 18:33:42 +00:00
|
|
|
vty_out(vty, " nse %u encapsulation framerelay-gre%s",
|
|
|
|
vtyvc->nsei, VTY_NEWLINE);
|
|
|
|
vty_out(vty, " nse %u remote-ip %s%s",
|
|
|
|
vtyvc->nsei,
|
|
|
|
vtyvc->remote.ip,
|
|
|
|
VTY_NEWLINE);
|
|
|
|
vty_out(vty, " nse %u fr-dlci %u%s",
|
|
|
|
vtyvc->nsei, vtyvc->frdlci,
|
|
|
|
VTY_NEWLINE);
|
2020-07-12 11:45:50 +00:00
|
|
|
break;
|
2020-11-19 01:34:49 +00:00
|
|
|
case GPRS_NS2_LL_FR:
|
2020-11-25 18:33:42 +00:00
|
|
|
vty_out(vty, " nse %u fr %s dlci %u%s",
|
|
|
|
vtyvc->nsei, vtyvc->netif, vtyvc->frdlci,
|
|
|
|
VTY_NEWLINE);
|
2020-11-18 23:41:29 +00:00
|
|
|
break;
|
2020-07-12 11:45:50 +00:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(vty_nsi->timeout); i++)
|
|
|
|
vty_out(vty, " timer %s %u%s",
|
|
|
|
get_value_string(gprs_ns_timer_strs, i),
|
|
|
|
vty_nsi->timeout[i], VTY_NEWLINE);
|
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
DEFUN(cfg_ns, cfg_ns_cmd,
|
|
|
|
"ns",
|
|
|
|
"Configure the GPRS Network Service")
|
|
|
|
{
|
|
|
|
vty->node = L_NS_NODE;
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void dump_nsvc(struct vty *vty, struct gprs_ns2_vc *nsvc, bool stats)
|
|
|
|
{
|
2020-12-01 17:17:28 +00:00
|
|
|
char nsvci_str[32];
|
|
|
|
|
|
|
|
if (nsvc->nsvci_is_valid)
|
|
|
|
snprintf(nsvci_str, sizeof(nsvci_str), "%05u", nsvc->nsvci);
|
|
|
|
else
|
|
|
|
snprintf(nsvci_str, sizeof(nsvci_str), "none");
|
|
|
|
|
|
|
|
vty_out(vty, " NSVCI %s: %s %s data_weight=%u sig_weight=%u %s%s", nsvci_str,
|
|
|
|
osmo_fsm_inst_state_name(nsvc->fi),
|
|
|
|
nsvc->persistent ? "PERSIST" : "DYNAMIC",
|
|
|
|
nsvc->data_weight, nsvc->sig_weight,
|
|
|
|
gprs_ns2_ll_str(nsvc), VTY_NEWLINE);
|
2020-07-12 11:45:50 +00:00
|
|
|
|
|
|
|
if (stats) {
|
2020-12-01 16:53:17 +00:00
|
|
|
vty_out_rate_ctr_group(vty, " ", nsvc->ctrg);
|
|
|
|
vty_out_stat_item_group(vty, " ", nsvc->statg);
|
2020-07-12 11:45:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void dump_nse(struct vty *vty, const struct gprs_ns2_nse *nse, bool stats, bool persistent_only)
|
|
|
|
{
|
|
|
|
struct gprs_ns2_vc *nsvc;
|
|
|
|
|
2020-12-01 16:51:07 +00:00
|
|
|
vty_out(vty, "NSEI %05u: %s, %s%s", nse->nsei, gprs_ns2_lltype_str(nse->ll),
|
|
|
|
nse->alive ? "ALIVE" : "DEAD", VTY_NEWLINE);
|
2020-07-12 11:45:50 +00:00
|
|
|
|
ns2: Properly indent VTY output
If multiple objects are printed in the VTY, only the first line of each
object should be on the first character of the line, all others should
be indented. With this patch the "snow ns entities" output becomes
much more readable:
OsmoGbProxy> show ns entities
NSEI 00102: UDP, DEAD
FSM Instance Name: 'GPRS-NS2-SNS-BSS(NSE00102-SNS)[0x6120000018a0]', ID: 'NSE00102-SNS'
Log-Level: 'DEBUG', State: 'SIZE'
Timer: 1
Maximum number of remote NS-VCs: 8, IPv4 Endpoints: 4, IPv6 Endpoints: 0
NSVCI none: UNCONFIGURED DYNAMIC data_weight=1 sig_weight=1 udp)[127.0.0.1]:23000<>[127.0.0.11]:8888
NSEI 00101: UDP, DEAD
FSM Instance Name: 'GPRS-NS2-SNS-BSS(NSE00101-SNS)[0x6120000015a0]', ID: 'NSE00101-SNS'
Log-Level: 'DEBUG', State: 'SIZE'
Timer: 1
Maximum number of remote NS-VCs: 8, IPv4 Endpoints: 4, IPv6 Endpoints: 0
NSVCI none: UNCONFIGURED DYNAMIC data_weight=1 sig_weight=1 udp)[127.0.0.1]:23000<>[127.0.0.10]:7777
Change-Id: Id1b4c80a6caef410076a68b4301adaa01ba7e57a
2021-01-19 19:58:33 +00:00
|
|
|
gprs_ns2_sns_dump_vty(vty, " ", nse, stats);
|
2020-07-12 11:45:50 +00:00
|
|
|
llist_for_each_entry(nsvc, &nse->nsvc, list) {
|
|
|
|
if (persistent_only) {
|
|
|
|
if (nsvc->persistent)
|
|
|
|
dump_nsvc(vty, nsvc, stats);
|
|
|
|
} else {
|
|
|
|
dump_nsvc(vty, nsvc, stats);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-02 00:34:39 +00:00
|
|
|
static void dump_bind(struct vty *vty, const struct gprs_ns2_vc_bind *bind, bool stats)
|
|
|
|
{
|
|
|
|
if (bind->dump_vty)
|
|
|
|
bind->dump_vty(bind, vty, stats);
|
|
|
|
}
|
|
|
|
|
2020-12-01 16:52:55 +00:00
|
|
|
static void dump_ns_bind(struct vty *vty, const struct gprs_ns2_inst *nsi, bool stats)
|
2020-07-12 11:45:50 +00:00
|
|
|
{
|
2020-10-02 00:34:39 +00:00
|
|
|
struct gprs_ns2_vc_bind *bind;
|
2020-07-12 11:45:50 +00:00
|
|
|
|
2020-10-02 00:34:39 +00:00
|
|
|
llist_for_each_entry(bind, &nsi->binding, list) {
|
|
|
|
dump_bind(vty, bind, stats);
|
|
|
|
}
|
2020-12-01 16:52:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void dump_ns_entities(struct vty *vty, const struct gprs_ns2_inst *nsi, bool stats, bool persistent_only)
|
|
|
|
{
|
|
|
|
struct gprs_ns2_nse *nse;
|
2020-10-02 00:34:39 +00:00
|
|
|
|
2020-07-12 11:45:50 +00:00
|
|
|
llist_for_each_entry(nse, &nsi->nse, list) {
|
|
|
|
dump_nse(vty, nse, stats, persistent_only);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-02 21:14:00 +00:00
|
|
|
/* Backwards compatibility, among other things for the TestVTYGbproxy which expects
|
|
|
|
* 'show ns' to output something about binds */
|
|
|
|
DEFUN_HIDDEN(show_ns, show_ns_cmd, "show ns",
|
|
|
|
SHOW_STR SHOW_NS_STR)
|
|
|
|
{
|
|
|
|
dump_ns_entities(vty, vty_nsi, false, false);
|
|
|
|
dump_ns_bind(vty, vty_nsi, false);
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-12-01 16:52:55 +00:00
|
|
|
DEFUN(show_ns_binds, show_ns_binds_cmd, "show ns binds [stats]",
|
2020-12-02 14:50:22 +00:00
|
|
|
SHOW_STR SHOW_NS_STR
|
2020-12-01 16:52:55 +00:00
|
|
|
"Display information about the NS protocol binds\n"
|
|
|
|
"Include statistic\n")
|
2020-07-12 11:45:50 +00:00
|
|
|
{
|
2020-12-01 16:52:55 +00:00
|
|
|
bool stats = false;
|
|
|
|
if (argc > 0)
|
|
|
|
stats = true;
|
|
|
|
|
|
|
|
dump_ns_bind(vty, vty_nsi, stats);
|
2020-07-12 11:45:50 +00:00
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2020-12-01 16:52:55 +00:00
|
|
|
DEFUN(show_ns_entities, show_ns_entities_cmd, "show ns entities [stats]",
|
2020-12-02 14:50:22 +00:00
|
|
|
SHOW_STR SHOW_NS_STR
|
2020-12-01 16:52:55 +00:00
|
|
|
"Display information about the NS protocol entities (NSEs)\n"
|
2020-07-12 11:45:50 +00:00
|
|
|
"Include statistics\n")
|
|
|
|
{
|
2020-12-01 16:52:55 +00:00
|
|
|
bool stats = false;
|
|
|
|
if (argc > 0)
|
|
|
|
stats = true;
|
|
|
|
|
|
|
|
dump_ns_entities(vty, vty_nsi, stats, false);
|
2020-07-12 11:45:50 +00:00
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
DEFUN(show_ns_pers, show_ns_pers_cmd, "show ns persistent",
|
2020-12-02 14:50:22 +00:00
|
|
|
SHOW_STR SHOW_NS_STR
|
2020-07-12 11:45:50 +00:00
|
|
|
"Show only persistent NS\n")
|
|
|
|
{
|
2020-12-01 16:52:55 +00:00
|
|
|
dump_ns_entities(vty, vty_nsi, true, true);
|
2020-07-12 11:45:50 +00:00
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
DEFUN(show_nse, show_nse_cmd, "show ns (nsei|nsvc) <0-65535> [stats]",
|
2020-12-02 14:50:22 +00:00
|
|
|
SHOW_STR SHOW_NS_STR
|
2020-07-12 11:45:50 +00:00
|
|
|
"Select one NSE by its NSE Identifier\n"
|
|
|
|
"Select one NSE by its NS-VC Identifier\n"
|
|
|
|
"The Identifier of selected type\n"
|
|
|
|
"Include Statistics\n")
|
|
|
|
{
|
|
|
|
struct gprs_ns2_inst *nsi = vty_nsi;
|
|
|
|
struct gprs_ns2_nse *nse;
|
|
|
|
struct gprs_ns2_vc *nsvc;
|
|
|
|
uint16_t id = atoi(argv[1]);
|
|
|
|
bool show_stats = false;
|
|
|
|
|
|
|
|
if (argc >= 3)
|
|
|
|
show_stats = true;
|
|
|
|
|
|
|
|
if (!strcmp(argv[0], "nsei")) {
|
|
|
|
nse = gprs_ns2_nse_by_nsei(nsi, id);
|
|
|
|
if (!nse) {
|
|
|
|
return CMD_WARNING;
|
|
|
|
}
|
|
|
|
|
|
|
|
dump_nse(vty, nse, show_stats, false);
|
|
|
|
} else {
|
|
|
|
nsvc = gprs_ns2_nsvc_by_nsvci(nsi, id);
|
|
|
|
|
|
|
|
if (!nsvc) {
|
|
|
|
vty_out(vty, "No such NS Entity%s", VTY_NEWLINE);
|
|
|
|
return CMD_WARNING;
|
|
|
|
}
|
|
|
|
|
|
|
|
dump_nsvc(vty, nsvc, show_stats);
|
|
|
|
}
|
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2020-11-18 13:19:56 +00:00
|
|
|
static int nsvc_force_unconf_cb(struct gprs_ns2_vc *nsvc, void *ctx)
|
|
|
|
{
|
|
|
|
gprs_ns2_vc_force_unconfigured(nsvc);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
DEFUN_HIDDEN(nsvc_force_unconf, nsvc_force_unconf_cmd,
|
|
|
|
"nsvc nsei <0-65535> force-unconfigured",
|
|
|
|
"NS Virtual Connection\n"
|
|
|
|
"The NSEI\n"
|
|
|
|
"Reset the NSVCs back to initial state\n"
|
|
|
|
)
|
|
|
|
{
|
|
|
|
struct gprs_ns2_inst *nsi = vty_nsi;
|
|
|
|
struct gprs_ns2_nse *nse;
|
|
|
|
|
|
|
|
uint16_t id = atoi(argv[0]);
|
|
|
|
|
|
|
|
nse = gprs_ns2_nse_by_nsei(nsi, id);
|
|
|
|
if (!nse) {
|
|
|
|
vty_out(vty, "Could not find NSE for NSEI %u%s", id, VTY_NEWLINE);
|
|
|
|
return CMD_WARNING;
|
|
|
|
}
|
|
|
|
|
2020-12-21 17:25:41 +00:00
|
|
|
if (nse->dialect == NS2_DIALECT_SNS) {
|
|
|
|
gprs_ns2_free_nsvcs(nse);
|
|
|
|
} else {
|
|
|
|
/* Perform the operation for all nsvc */
|
|
|
|
gprs_ns2_nse_foreach_nsvc(nse, nsvc_force_unconf_cb, NULL);
|
|
|
|
}
|
2020-11-18 13:19:56 +00:00
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2020-07-12 11:45:50 +00:00
|
|
|
#define NSE_CMD_STR "Persistent NS Entity\n" "NS Entity ID (NSEI)\n"
|
|
|
|
|
2020-11-18 23:41:29 +00:00
|
|
|
DEFUN(cfg_nse_fr, cfg_nse_fr_cmd,
|
|
|
|
"nse <0-65535> nsvci <0-65535> (fr|frnet) NETIF dlci <0-1023>",
|
|
|
|
NSE_CMD_STR
|
|
|
|
"NS Virtual Connection\n"
|
|
|
|
"NS Virtual Connection ID (NSVCI)\n"
|
2020-11-25 19:56:06 +00:00
|
|
|
"Frame Relay User-Side\n"
|
|
|
|
"Frame Relay Network-Side\n"
|
2020-11-18 23:41:29 +00:00
|
|
|
IFNAME_STR
|
|
|
|
"Data Link connection identifier\n"
|
|
|
|
"Data Link connection identifier\n"
|
|
|
|
)
|
|
|
|
{
|
|
|
|
struct ns2_vty_vc *vtyvc;
|
|
|
|
|
|
|
|
uint16_t nsei = atoi(argv[0]);
|
|
|
|
uint16_t nsvci = atoi(argv[1]);
|
|
|
|
const char *role = argv[2];
|
|
|
|
const char *name = argv[3];
|
|
|
|
uint16_t dlci = atoi(argv[4]);
|
|
|
|
|
2020-11-25 18:33:42 +00:00
|
|
|
vtyvc = vtyvc_by_nsei(nsei, true);
|
2020-11-18 23:41:29 +00:00
|
|
|
if (!vtyvc) {
|
|
|
|
vty_out(vty, "Can not allocate space %s", VTY_NEWLINE);
|
|
|
|
return CMD_WARNING;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!strcmp(role, "fr"))
|
|
|
|
vtyvc->fr.role = FR_ROLE_USER_EQUIPMENT;
|
|
|
|
else if (!strcmp(role, "frnet"))
|
|
|
|
vtyvc->fr.role = FR_ROLE_NETWORK_EQUIPMENT;
|
|
|
|
|
|
|
|
osmo_strlcpy(vtyvc->netif, name, sizeof(vtyvc->netif));
|
|
|
|
vtyvc->frdlci = dlci;
|
|
|
|
vtyvc->nsvci = nsvci;
|
2020-11-19 01:34:49 +00:00
|
|
|
vtyvc->ll = GPRS_NS2_LL_FR;
|
2020-11-18 23:41:29 +00:00
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2020-07-12 11:45:50 +00:00
|
|
|
DEFUN(cfg_nse_nsvc, cfg_nse_nsvci_cmd,
|
|
|
|
"nse <0-65535> nsvci <0-65535>",
|
|
|
|
NSE_CMD_STR
|
|
|
|
"NS Virtual Connection\n"
|
|
|
|
"NS Virtual Connection ID (NSVCI)\n"
|
|
|
|
)
|
|
|
|
{
|
|
|
|
struct ns2_vty_vc *vtyvc;
|
|
|
|
|
|
|
|
uint16_t nsei = atoi(argv[0]);
|
|
|
|
uint16_t nsvci = atoi(argv[1]);
|
|
|
|
|
2020-11-25 18:33:42 +00:00
|
|
|
vtyvc = vtyvc_by_nsei(nsei, true);
|
2020-07-12 11:45:50 +00:00
|
|
|
if (!vtyvc) {
|
|
|
|
vty_out(vty, "Can not allocate space %s", VTY_NEWLINE);
|
|
|
|
return CMD_WARNING;
|
|
|
|
}
|
|
|
|
|
|
|
|
vtyvc->nsvci = nsvci;
|
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
DEFUN(cfg_nse_remoteip, cfg_nse_remoteip_cmd,
|
2020-11-25 18:33:42 +00:00
|
|
|
"nse <0-65535> remote-ip " VTY_IPV46_CMD,
|
2020-07-12 11:45:50 +00:00
|
|
|
NSE_CMD_STR
|
|
|
|
"Remote IP Address\n"
|
2020-09-24 03:55:48 +00:00
|
|
|
"Remote IPv4 Address\n"
|
|
|
|
"Remote IPv6 Address\n")
|
2020-07-12 11:45:50 +00:00
|
|
|
{
|
|
|
|
uint16_t nsei = atoi(argv[0]);
|
|
|
|
struct ns2_vty_vc *vtyvc;
|
|
|
|
|
2020-11-25 18:33:42 +00:00
|
|
|
vtyvc = vtyvc_by_nsei(nsei, true);
|
2020-07-12 11:45:50 +00:00
|
|
|
if (!vtyvc) {
|
|
|
|
vty_out(vty, "Can not allocate space %s", VTY_NEWLINE);
|
|
|
|
return CMD_WARNING;
|
|
|
|
}
|
|
|
|
|
2020-11-25 18:33:42 +00:00
|
|
|
osmo_sockaddr_str_from_str2(&vtyvc->remote, argv[1]);
|
2020-07-12 11:45:50 +00:00
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
DEFUN(cfg_nse_remoteport, cfg_nse_remoteport_cmd,
|
2020-11-25 18:33:42 +00:00
|
|
|
"nse <0-65535> remote-port <0-65535>",
|
2020-07-12 11:45:50 +00:00
|
|
|
NSE_CMD_STR
|
|
|
|
"Remote UDP Port\n"
|
|
|
|
"Remote UDP Port Number\n")
|
|
|
|
{
|
|
|
|
uint16_t nsei = atoi(argv[0]);
|
2020-11-25 18:33:42 +00:00
|
|
|
uint16_t port = atoi(argv[1]);
|
2020-07-12 11:45:50 +00:00
|
|
|
struct ns2_vty_vc *vtyvc;
|
|
|
|
|
2020-11-25 18:33:42 +00:00
|
|
|
vtyvc = vtyvc_by_nsei(nsei, true);
|
2020-07-12 11:45:50 +00:00
|
|
|
if (!vtyvc) {
|
|
|
|
vty_out(vty, "Can not allocate space %s", VTY_NEWLINE);
|
|
|
|
return CMD_WARNING;
|
|
|
|
}
|
|
|
|
|
|
|
|
vtyvc->remote.port = port;
|
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
DEFUN(cfg_nse_fr_dlci, cfg_nse_fr_dlci_cmd,
|
2020-11-18 23:41:29 +00:00
|
|
|
"nse <0-65535> nsvci <0-65535> fr-dlci <16-1007>",
|
2020-07-12 11:45:50 +00:00
|
|
|
NSE_CMD_STR
|
2020-11-25 19:56:06 +00:00
|
|
|
"NS Virtual Connection\n"
|
|
|
|
"NS Virtual Connection ID (NSVCI)\n"
|
2020-07-12 11:45:50 +00:00
|
|
|
"Frame Relay DLCI\n"
|
|
|
|
"Frame Relay DLCI Number\n")
|
|
|
|
{
|
|
|
|
uint16_t nsei = atoi(argv[0]);
|
2020-11-18 23:41:29 +00:00
|
|
|
uint16_t nsvci = atoi(argv[1]);
|
|
|
|
uint16_t dlci = atoi(argv[2]);
|
2020-07-12 11:45:50 +00:00
|
|
|
struct ns2_vty_vc *vtyvc;
|
|
|
|
|
2020-11-25 18:33:42 +00:00
|
|
|
vtyvc = vtyvc_by_nsei(nsei, true);
|
2020-07-12 11:45:50 +00:00
|
|
|
if (!vtyvc) {
|
|
|
|
vty_out(vty, "Can not allocate space %s", VTY_NEWLINE);
|
|
|
|
return CMD_WARNING;
|
|
|
|
}
|
|
|
|
|
|
|
|
vtyvc->frdlci = dlci;
|
2020-11-25 18:33:42 +00:00
|
|
|
vtyvc->nsvci = nsvci;
|
2020-07-12 11:45:50 +00:00
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
DEFUN(cfg_nse_encaps, cfg_nse_encaps_cmd,
|
2020-11-25 18:33:42 +00:00
|
|
|
"nse <0-65535> encapsulation (udp|framerelay-gre)",
|
2020-07-12 11:45:50 +00:00
|
|
|
NSE_CMD_STR
|
|
|
|
"Encapsulation for NS\n"
|
|
|
|
"UDP/IP Encapsulation\n" "Frame-Relay/GRE/IP Encapsulation\n")
|
|
|
|
{
|
|
|
|
uint16_t nsei = atoi(argv[0]);
|
|
|
|
struct ns2_vty_vc *vtyvc;
|
|
|
|
|
2020-11-25 18:33:42 +00:00
|
|
|
vtyvc = vtyvc_by_nsei(nsei, true);
|
2020-07-12 11:45:50 +00:00
|
|
|
if (!vtyvc) {
|
|
|
|
vty_out(vty, "Can not allocate space %s", VTY_NEWLINE);
|
|
|
|
return CMD_WARNING;
|
|
|
|
}
|
|
|
|
|
2020-11-25 18:33:42 +00:00
|
|
|
if (!strcmp(argv[1], "udp"))
|
2020-11-19 01:34:49 +00:00
|
|
|
vtyvc->ll = GPRS_NS2_LL_UDP;
|
2020-07-12 11:45:50 +00:00
|
|
|
else
|
2020-11-19 01:34:49 +00:00
|
|
|
vtyvc->ll = GPRS_NS2_LL_FR_GRE;
|
2020-07-12 11:45:50 +00:00
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
DEFUN(cfg_nse_remoterole, cfg_nse_remoterole_cmd,
|
2020-11-25 18:33:42 +00:00
|
|
|
"nse <0-65535> remote-role (sgsn|bss)",
|
2020-07-12 11:45:50 +00:00
|
|
|
NSE_CMD_STR
|
|
|
|
"Remote NSE Role\n"
|
|
|
|
"Remote Peer is SGSN\n"
|
|
|
|
"Remote Peer is BSS\n")
|
|
|
|
{
|
|
|
|
uint16_t nsei = atoi(argv[0]);
|
|
|
|
struct ns2_vty_vc *vtyvc;
|
|
|
|
|
2020-11-25 18:33:42 +00:00
|
|
|
vtyvc = vtyvc_by_nsei(nsei, true);
|
2020-07-12 11:45:50 +00:00
|
|
|
if (!vtyvc) {
|
|
|
|
vty_out(vty, "Can not allocate space %s", VTY_NEWLINE);
|
|
|
|
return CMD_WARNING;
|
|
|
|
}
|
|
|
|
|
2020-11-25 18:33:42 +00:00
|
|
|
if (!strcmp(argv[1], "sgsn"))
|
2020-07-12 11:45:50 +00:00
|
|
|
vtyvc->remote_end_is_sgsn = 1;
|
|
|
|
else
|
|
|
|
vtyvc->remote_end_is_sgsn = 0;
|
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
DEFUN(cfg_no_nse, cfg_no_nse_cmd,
|
2020-11-25 18:33:42 +00:00
|
|
|
"no nse <0-65535>",
|
2020-07-12 11:45:50 +00:00
|
|
|
"Delete Persistent NS Entity\n"
|
|
|
|
"Delete " NSE_CMD_STR)
|
|
|
|
{
|
|
|
|
uint16_t nsei = atoi(argv[0]);
|
|
|
|
struct ns2_vty_vc *vtyvc;
|
|
|
|
|
2020-11-25 18:33:42 +00:00
|
|
|
vtyvc = vtyvc_by_nsei(nsei, false);
|
2020-07-12 11:45:50 +00:00
|
|
|
if (!vtyvc) {
|
|
|
|
vty_out(vty, "The NSE %d does not exists.%s", nsei, VTY_NEWLINE);
|
|
|
|
return CMD_WARNING;
|
|
|
|
}
|
|
|
|
|
|
|
|
ns2_vc_free(vtyvc);
|
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
DEFUN(cfg_ns_timer, cfg_ns_timer_cmd,
|
|
|
|
"timer " NS_TIMERS " <0-65535>",
|
|
|
|
"Network Service Timer\n"
|
|
|
|
NS_TIMERS_HELP "Timer Value\n")
|
|
|
|
{
|
|
|
|
int idx = get_string_value(gprs_ns_timer_strs, argv[0]);
|
|
|
|
int val = atoi(argv[1]);
|
|
|
|
|
|
|
|
if (idx < 0 || idx >= ARRAY_SIZE(vty_nsi->timeout))
|
|
|
|
return CMD_WARNING;
|
|
|
|
|
|
|
|
vty_nsi->timeout[idx] = val;
|
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define ENCAPS_STR "NS encapsulation options\n"
|
|
|
|
|
|
|
|
DEFUN(cfg_nsip_local_ip, cfg_nsip_local_ip_cmd,
|
|
|
|
"encapsulation udp local-ip " VTY_IPV46_CMD,
|
|
|
|
ENCAPS_STR "NS over UDP Encapsulation\n"
|
|
|
|
"Set the IP address on which we listen for NS/UDP\n"
|
2020-09-24 03:55:48 +00:00
|
|
|
"IPv4 Address\n"
|
|
|
|
"IPv6 Address\n")
|
2020-07-12 11:45:50 +00:00
|
|
|
{
|
|
|
|
osmo_sockaddr_str_from_str2(&priv.udp, argv[0]);
|
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
DEFUN(cfg_nsip_local_port, cfg_nsip_local_port_cmd,
|
|
|
|
"encapsulation udp local-port <0-65535>",
|
|
|
|
ENCAPS_STR "NS over UDP Encapsulation\n"
|
|
|
|
"Set the UDP port on which we listen for NS/UDP\n"
|
|
|
|
"UDP port number\n")
|
|
|
|
{
|
|
|
|
unsigned int port = atoi(argv[0]);
|
|
|
|
|
|
|
|
priv.udp.port = port;
|
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
DEFUN(cfg_nsip_dscp, cfg_nsip_dscp_cmd,
|
|
|
|
"encapsulation udp dscp <0-255>",
|
|
|
|
ENCAPS_STR "NS over UDP Encapsulation\n"
|
|
|
|
"Set DSCP/TOS on the UDP socket\n" "DSCP Value\n")
|
|
|
|
{
|
|
|
|
int dscp = atoi(argv[0]);
|
|
|
|
struct gprs_ns2_vc_bind *bind;
|
|
|
|
|
|
|
|
priv.dscp = dscp;
|
|
|
|
|
|
|
|
llist_for_each_entry(bind, &vty_nsi->binding, list) {
|
|
|
|
if (gprs_ns2_is_ip_bind(bind))
|
|
|
|
gprs_ns2_ip_bind_set_dscp(bind, dscp);
|
|
|
|
}
|
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
DEFUN(cfg_nsip_res_block_unblock, cfg_nsip_res_block_unblock_cmd,
|
|
|
|
"encapsulation udp use-reset-block-unblock (enabled|disabled)",
|
|
|
|
ENCAPS_STR "NS over UDP Encapsulation\n"
|
|
|
|
"Use NS-{RESET,BLOCK,UNBLOCK} procedures in violation of 3GPP TS 48.016\n"
|
|
|
|
"Enable NS-{RESET,BLOCK,UNBLOCK}\n"
|
|
|
|
"Disable NS-{RESET,BLOCK,UNBLOCK}\n")
|
|
|
|
{
|
|
|
|
enum gprs_ns2_vc_mode vc_mode;
|
|
|
|
|
|
|
|
if (!strcmp(argv[0], "enabled"))
|
|
|
|
vc_mode = NS2_VC_MODE_BLOCKRESET;
|
|
|
|
else
|
|
|
|
vc_mode = NS2_VC_MODE_ALIVE;
|
|
|
|
|
|
|
|
priv.vc_mode = vc_mode;
|
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
DEFUN(cfg_frgre_local_ip, cfg_frgre_local_ip_cmd,
|
|
|
|
"encapsulation framerelay-gre local-ip " VTY_IPV46_CMD,
|
|
|
|
ENCAPS_STR "NS over Frame Relay over GRE Encapsulation\n"
|
|
|
|
"Set the IP address on which we listen for NS/FR/GRE\n"
|
2020-09-24 03:55:48 +00:00
|
|
|
"IPv4 Address\n"
|
|
|
|
"IPv6 Address\n")
|
2020-07-12 11:45:50 +00:00
|
|
|
{
|
|
|
|
osmo_sockaddr_str_from_str2(&priv.frgreaddr, argv[0]);
|
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
DEFUN(cfg_frgre_enable, cfg_frgre_enable_cmd,
|
|
|
|
"encapsulation framerelay-gre enabled (1|0)",
|
|
|
|
ENCAPS_STR "NS over Frame Relay over GRE Encapsulation\n"
|
|
|
|
"Enable or disable Frame Relay over GRE\n"
|
|
|
|
"Enable\n" "Disable\n")
|
|
|
|
{
|
|
|
|
int enabled = atoi(argv[0]);
|
|
|
|
|
|
|
|
priv.frgre = enabled;
|
|
|
|
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* TODO: allow vty to reset/block/unblock nsvc/nsei */
|
|
|
|
|
2020-12-02 17:59:44 +00:00
|
|
|
DEFUN(logging_fltr_nse,
|
|
|
|
logging_fltr_nse_cmd,
|
|
|
|
"logging filter nse nsei <0-65535>",
|
|
|
|
LOGGING_STR FILTER_STR
|
|
|
|
"Filter based on NS Entity\n"
|
|
|
|
"Identify NSE by NSEI\n"
|
|
|
|
"Numeric identifier\n")
|
|
|
|
{
|
|
|
|
struct log_target *tgt;
|
|
|
|
struct gprs_ns2_nse *nse;
|
2020-12-04 00:36:59 +00:00
|
|
|
uint16_t id = atoi(argv[0]);
|
2020-12-02 17:59:44 +00:00
|
|
|
|
|
|
|
log_tgt_mutex_lock();
|
|
|
|
tgt = osmo_log_vty2tgt(vty);
|
|
|
|
if (!tgt) {
|
|
|
|
log_tgt_mutex_unlock();
|
|
|
|
return CMD_WARNING;
|
|
|
|
}
|
|
|
|
|
|
|
|
nse = gprs_ns2_nse_by_nsei(vty_nsi, id);
|
|
|
|
if (!nse) {
|
|
|
|
vty_out(vty, "No NSE by that identifier%s", VTY_NEWLINE);
|
|
|
|
log_tgt_mutex_unlock();
|
|
|
|
return CMD_WARNING;
|
|
|
|
}
|
|
|
|
|
|
|
|
log_set_nse_filter(tgt, nse);
|
|
|
|
log_tgt_mutex_unlock();
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2020-07-12 11:45:50 +00:00
|
|
|
/* TODO: add filter for single connection by description */
|
|
|
|
DEFUN(logging_fltr_nsvc,
|
|
|
|
logging_fltr_nsvc_cmd,
|
|
|
|
"logging filter nsvc nsvci <0-65535>",
|
|
|
|
LOGGING_STR FILTER_STR
|
|
|
|
"Filter based on NS Virtual Connection\n"
|
|
|
|
"Identify NS-VC by NSVCI\n"
|
|
|
|
"Numeric identifier\n")
|
|
|
|
{
|
|
|
|
struct log_target *tgt;
|
|
|
|
struct gprs_ns2_vc *nsvc;
|
2020-12-04 00:36:59 +00:00
|
|
|
uint16_t id = atoi(argv[0]);
|
2020-07-12 11:45:50 +00:00
|
|
|
|
|
|
|
log_tgt_mutex_lock();
|
|
|
|
tgt = osmo_log_vty2tgt(vty);
|
|
|
|
if (!tgt) {
|
|
|
|
log_tgt_mutex_unlock();
|
|
|
|
return CMD_WARNING;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsvc = gprs_ns2_nsvc_by_nsvci(vty_nsi, id);
|
|
|
|
if (!nsvc) {
|
|
|
|
vty_out(vty, "No NS-VC by that identifier%s", VTY_NEWLINE);
|
|
|
|
log_tgt_mutex_unlock();
|
|
|
|
return CMD_WARNING;
|
|
|
|
}
|
|
|
|
|
|
|
|
log_set_nsvc_filter(tgt, nsvc);
|
|
|
|
log_tgt_mutex_unlock();
|
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2020-10-01 17:08:38 +00:00
|
|
|
/**
|
|
|
|
* gprs_ns2_vty_init initialize the vty
|
|
|
|
* \param[inout] nsi
|
|
|
|
* \param[in] default_bind set the default address to bind to. Can be NULL.
|
|
|
|
* \return 0 on success
|
|
|
|
*/
|
2020-10-09 14:47:01 +00:00
|
|
|
int gprs_ns2_vty_init(struct gprs_ns2_inst *nsi,
|
|
|
|
const struct osmo_sockaddr_str *default_bind)
|
2020-07-12 11:45:50 +00:00
|
|
|
{
|
|
|
|
static bool vty_elements_installed = false;
|
|
|
|
|
|
|
|
vty_nsi = nsi;
|
|
|
|
memset(&priv, 0, sizeof(struct ns2_vty_priv));
|
|
|
|
INIT_LLIST_HEAD(&priv.vtyvc);
|
|
|
|
priv.vc_mode = NS2_VC_MODE_BLOCKRESET;
|
2020-10-01 17:08:38 +00:00
|
|
|
if (default_bind)
|
|
|
|
memcpy(&priv.udp, default_bind, sizeof(*default_bind));
|
2020-07-12 11:45:50 +00:00
|
|
|
|
|
|
|
/* Regression test code may call this function repeatedly, so make sure
|
|
|
|
* that VTY elements are not duplicated, which would assert. */
|
|
|
|
if (vty_elements_installed)
|
|
|
|
return 0;
|
|
|
|
vty_elements_installed = true;
|
|
|
|
|
2020-12-02 21:14:00 +00:00
|
|
|
install_lib_element_ve(&show_ns_cmd);
|
2020-12-01 16:52:55 +00:00
|
|
|
install_lib_element_ve(&show_ns_binds_cmd);
|
|
|
|
install_lib_element_ve(&show_ns_entities_cmd);
|
2020-10-04 08:37:31 +00:00
|
|
|
install_lib_element_ve(&show_ns_pers_cmd);
|
|
|
|
install_lib_element_ve(&show_nse_cmd);
|
2020-12-02 17:59:44 +00:00
|
|
|
install_lib_element_ve(&logging_fltr_nse_cmd);
|
2020-10-04 08:37:31 +00:00
|
|
|
install_lib_element_ve(&logging_fltr_nsvc_cmd);
|
2020-07-12 11:45:50 +00:00
|
|
|
|
2020-11-18 13:19:56 +00:00
|
|
|
install_lib_element(ENABLE_NODE, &nsvc_force_unconf_cmd);
|
|
|
|
|
2020-12-02 17:59:44 +00:00
|
|
|
install_lib_element(CFG_LOG_NODE, &logging_fltr_nse_cmd);
|
2020-10-04 08:37:31 +00:00
|
|
|
install_lib_element(CFG_LOG_NODE, &logging_fltr_nsvc_cmd);
|
2020-07-12 11:45:50 +00:00
|
|
|
|
2020-10-04 08:37:31 +00:00
|
|
|
install_lib_element(CONFIG_NODE, &cfg_ns_cmd);
|
2020-07-12 11:45:50 +00:00
|
|
|
install_node(&ns_node, config_write_ns);
|
2020-11-18 23:41:29 +00:00
|
|
|
install_lib_element(L_NS_NODE, &cfg_nse_fr_cmd);
|
2020-10-04 08:37:31 +00:00
|
|
|
install_lib_element(L_NS_NODE, &cfg_nse_nsvci_cmd);
|
|
|
|
install_lib_element(L_NS_NODE, &cfg_nse_remoteip_cmd);
|
|
|
|
install_lib_element(L_NS_NODE, &cfg_nse_remoteport_cmd);
|
|
|
|
install_lib_element(L_NS_NODE, &cfg_nse_fr_dlci_cmd);
|
|
|
|
install_lib_element(L_NS_NODE, &cfg_nse_encaps_cmd);
|
|
|
|
install_lib_element(L_NS_NODE, &cfg_nse_remoterole_cmd);
|
|
|
|
install_lib_element(L_NS_NODE, &cfg_no_nse_cmd);
|
|
|
|
install_lib_element(L_NS_NODE, &cfg_ns_timer_cmd);
|
|
|
|
install_lib_element(L_NS_NODE, &cfg_nsip_local_ip_cmd);
|
|
|
|
install_lib_element(L_NS_NODE, &cfg_nsip_local_port_cmd);
|
|
|
|
install_lib_element(L_NS_NODE, &cfg_nsip_dscp_cmd);
|
|
|
|
install_lib_element(L_NS_NODE, &cfg_nsip_res_block_unblock_cmd);
|
|
|
|
install_lib_element(L_NS_NODE, &cfg_frgre_enable_cmd);
|
|
|
|
install_lib_element(L_NS_NODE, &cfg_frgre_local_ip_cmd);
|
2020-07-12 11:45:50 +00:00
|
|
|
|
|
|
|
/* TODO: nsvc/nsei command to reset states or reset/block/unblock nsei/nsvcs */
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief gprs_ns2_vty_create parse the vty tree into ns nodes
|
|
|
|
* It has to be in different steps to ensure the bind is created before creating VCs.
|
|
|
|
* \return 0 on success
|
|
|
|
*/
|
|
|
|
int gprs_ns2_vty_create() {
|
|
|
|
struct ns2_vty_vc *vtyvc;
|
2020-11-18 23:41:29 +00:00
|
|
|
struct gprs_ns2_vc_bind *bind, *fr;
|
2020-07-12 11:45:50 +00:00
|
|
|
struct gprs_ns2_nse *nse;
|
|
|
|
struct gprs_ns2_vc *nsvc;
|
|
|
|
struct osmo_sockaddr sockaddr;
|
2020-12-01 00:03:52 +00:00
|
|
|
enum gprs_ns2_dialect dialect = NS2_DIALECT_UNDEF;
|
2020-11-18 23:41:29 +00:00
|
|
|
int rc = 0;
|
2020-07-12 11:45:50 +00:00
|
|
|
|
|
|
|
if (!vty_nsi)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
/* create binds, only support a single bind. either FR or UDP */
|
|
|
|
if (priv.frgre) {
|
|
|
|
/* TODO not yet supported !*/
|
|
|
|
return -1;
|
|
|
|
} else {
|
|
|
|
/* UDP */
|
|
|
|
osmo_sockaddr_str_to_sockaddr(&priv.udp, &sockaddr.u.sas);
|
2020-12-03 05:02:03 +00:00
|
|
|
if (gprs_ns2_ip_bind(vty_nsi, "vtybind", &sockaddr, priv.dscp, &bind)) {
|
2020-07-12 11:45:50 +00:00
|
|
|
/* TODO: could not bind on the specific address */
|
|
|
|
return -1;
|
|
|
|
}
|
2020-12-16 19:33:34 +00:00
|
|
|
|
|
|
|
bind->accept_ipaccess = priv.vc_mode == NS2_VC_MODE_BLOCKRESET;
|
2020-07-12 11:45:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* create vcs */
|
|
|
|
llist_for_each_entry(vtyvc, &priv.vtyvc, list) {
|
2020-11-18 23:41:29 +00:00
|
|
|
/* validate settings */
|
|
|
|
switch (vtyvc->ll) {
|
2020-11-19 01:34:49 +00:00
|
|
|
case GPRS_NS2_LL_UDP:
|
2020-12-16 19:33:34 +00:00
|
|
|
if (priv.vc_mode == NS2_VC_MODE_BLOCKRESET)
|
|
|
|
dialect = NS2_DIALECT_IPACCESS;
|
|
|
|
else
|
|
|
|
dialect = NS2_DIALECT_STATIC_ALIVE;
|
2020-11-18 23:41:29 +00:00
|
|
|
if (strlen(vtyvc->remote.ip) == 0) {
|
|
|
|
/* Invalid IP for VC */
|
|
|
|
continue;
|
|
|
|
}
|
2020-07-12 11:45:50 +00:00
|
|
|
|
2020-11-18 23:41:29 +00:00
|
|
|
if (!vtyvc->remote.port) {
|
|
|
|
/* Invalid port for VC */
|
|
|
|
continue;
|
|
|
|
}
|
2020-07-12 11:45:50 +00:00
|
|
|
|
2020-11-18 23:41:29 +00:00
|
|
|
if (osmo_sockaddr_str_to_sockaddr(&vtyvc->remote, &sockaddr.u.sas)) {
|
|
|
|
/* Invalid sockaddr for VC */
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
break;
|
2020-11-19 01:34:49 +00:00
|
|
|
case GPRS_NS2_LL_FR:
|
2020-12-01 00:03:52 +00:00
|
|
|
dialect = NS2_DIALECT_STATIC_RESETBLOCK;
|
2020-11-18 23:41:29 +00:00
|
|
|
break;
|
2020-11-19 01:34:49 +00:00
|
|
|
case GPRS_NS2_LL_FR_GRE:
|
2020-12-01 00:03:52 +00:00
|
|
|
dialect = NS2_DIALECT_STATIC_RESETBLOCK;
|
2020-07-12 11:45:50 +00:00
|
|
|
continue;
|
2020-11-19 04:24:37 +00:00
|
|
|
case GPRS_NS2_LL_UNDEF:
|
|
|
|
/* should not happen */
|
|
|
|
OSMO_ASSERT(false);
|
2020-07-12 11:45:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
nse = gprs_ns2_nse_by_nsei(vty_nsi, vtyvc->nsei);
|
|
|
|
if (!nse) {
|
2020-12-01 00:03:52 +00:00
|
|
|
nse = gprs_ns2_create_nse(vty_nsi, vtyvc->nsei, vtyvc->ll, dialect);
|
2020-07-12 11:45:50 +00:00
|
|
|
if (!nse) {
|
|
|
|
/* Could not create NSE for VTY */
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
nse->persistent = true;
|
|
|
|
|
2020-11-18 23:41:29 +00:00
|
|
|
switch (vtyvc->ll) {
|
2020-11-19 01:34:49 +00:00
|
|
|
case GPRS_NS2_LL_UDP:
|
2020-11-18 23:41:29 +00:00
|
|
|
nsvc = gprs_ns2_ip_connect(bind,
|
|
|
|
&sockaddr,
|
|
|
|
nse,
|
|
|
|
vtyvc->nsvci);
|
|
|
|
if (!nsvc) {
|
|
|
|
/* Could not create NSVC, connect failed */
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
nsvc->persistent = true;
|
|
|
|
break;
|
2020-11-19 01:34:49 +00:00
|
|
|
case GPRS_NS2_LL_FR: {
|
2020-11-18 23:41:29 +00:00
|
|
|
if (vty_fr_network == NULL) {
|
|
|
|
/* TODO: add a switch for BSS/SGSN/gbproxy */
|
|
|
|
vty_fr_network = osmo_fr_network_alloc(vty_nsi);
|
|
|
|
}
|
|
|
|
fr = gprs_ns2_fr_bind_by_netif(
|
|
|
|
vty_nsi,
|
|
|
|
vtyvc->netif);
|
|
|
|
if (!fr) {
|
2020-12-03 05:02:03 +00:00
|
|
|
rc = gprs_ns2_fr_bind(vty_nsi, vtyvc->netif, vtyvc->netif, vty_fr_network, vtyvc->fr.role, &fr);
|
2020-11-18 23:41:29 +00:00
|
|
|
if (rc < 0) {
|
|
|
|
LOGP(DLNS, LOGL_ERROR, "Can not create fr bind on device %s err: %d\n", vtyvc->netif, rc);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-03 05:11:39 +00:00
|
|
|
nsvc = gprs_ns2_fr_connect(fr, nse, vtyvc->nsvci, vtyvc->frdlci);
|
2020-11-18 23:41:29 +00:00
|
|
|
if (!nsvc) {
|
|
|
|
/* Could not create NSVC, connect failed */
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
nsvc->persistent = true;
|
|
|
|
break;
|
|
|
|
}
|
2020-11-19 01:34:49 +00:00
|
|
|
case GPRS_NS2_LL_FR_GRE:
|
2020-11-19 04:24:37 +00:00
|
|
|
case GPRS_NS2_LL_UNDEF:
|
2020-10-06 22:50:00 +00:00
|
|
|
continue;
|
2020-07-12 11:45:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|