/* GPRS Networks Service (NS) messages on the Gb interface
* 3GPP TS 08.16 version 8.0.1 Release 1999 / ETSI TS 101 299 V8.0.1 (2002-05) */
/* (C) 2009-2012 by Harald Welte <laforge@gnumonks.org>
*
* All Rights Reserved
*
* 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/>.
*
*/
/*! \addtogroup libgb
* @{
*/
/*! \file gprs_ns.c */
/*!
* GPRS Networks Service (NS) messages on the Gb interface
* 3GPP TS 08.16 version 8.0.1 Release 1999 / ETSI TS 101 299 V8.0.1 (2002-05)
*
* Some introduction into NS: NS is used typically on top of frame relay,
* but in the ip.access world it is encapsulated in UDP packets. It serves
* as an intermediate shim betwen BSSGP and the underlying medium. It doesn't
* do much, apart from providing congestion notification and status indication.
*
* Terms:
* NS Network Service
* NSVC NS Virtual Connection
* NSEI NS Entity Identifier
* NSVL NS Virtual Link
* NSVLI NS Virtual Link Identifier
* BVC BSSGP Virtual Connection
* BVCI BSSGP Virtual Connection Identifier
* NSVCG NS Virtual Connection Goup
* Blocked NS-VC cannot be used for user traffic
* Alive Ability of a NS-VC to provide communication
*
* There can be multiple BSSGP virtual connections over one (group of) NSVC's. BSSGP will
* therefore identify the BSSGP virtual connection by a BVCI passed down to NS.
* NS then has to firgure out which NSVC's are responsible for this BVCI.
* Those mappings are administratively configured.
*/
/* This implementation has the following limitations:
* o Only one NS-VC for each NSE: No load-sharing function
* o NSVCI 65535 and 65534 are reserved for internal use
* o Only UDP is supported as of now, no frame relay support
* o The IP Sub-Network-Service (SNS) as specified in 48.016 is not implemented
* o There are no BLOCK and UNBLOCK timers (yet?)
*/
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <osmocom/core/msgb.h>
#include <osmocom/gsm/tlv.h>
#include <osmocom/core/talloc.h>
#include <osmocom/core/select.h>
#include <osmocom/core/rate_ctr.h>
#include <osmocom/core/stat_item.h>
#include <osmocom/core/stats.h>
#include <osmocom/core/socket.h>
#include <osmocom/core/signal.h>
#include <osmocom/gprs/gprs_ns.h>
#include <osmocom/gprs/gprs_bssgp.h>
#include <osmocom/gprs/gprs_ns_frgre.h>
#include "common_vty.h"
static const struct tlv_definition ns_att_tlvdef = {
.def = {
[NS_IE_CAUSE] = { TLV_TYPE_TvLV, 0 },
[NS_IE_VCI] = { TLV_TYPE_TvLV, 0 },
[NS_IE_PDU] = { TLV_TYPE_TvLV, 0 },
[NS_IE_BVCI] = { TLV_TYPE_TvLV, 0 },
[NS_IE_NSEI] = { TLV_TYPE_TvLV, 0 },
},
};
enum ns_ctr {
NS_CTR_PKTS_IN,
NS_CTR_PKTS_OUT,
NS_CTR_BYTES_IN,
NS_CTR_BYTES_OUT,
NS_CTR_BLOCKED,
NS_CTR_DEAD,
NS_CTR_REPLACED,
NS_CTR_NSEI_CHG,
NS_CTR_INV_VCI,
NS_CTR_INV_NSEI,
NS_CTR_LOST_ALIVE,
NS_CTR_LOST_RESET,
};
static const struct rate_ctr_desc nsvc_ctr_description[] = {
{ "packets.in", "Packets at NS Level ( In)" },
{ "packets.out","Packets at NS Level (Out)" },
{ "bytes.in", "Bytes at NS Level ( In)" },
{ "bytes.out", "Bytes at NS Level (Out)" },
{ "blocked", "NS-VC Block count " },
{ "dead", "NS-VC gone dead count " },
{ "replaced", "NS-VC replaced other count" },
{ "nsei-chg", "NS-VC changed NSEI count " },
{ "inv-nsvci", "NS-VCI was invalid count " },
{ "inv-nsei", "NSEI was invalid count " },
{ "lost.alive", "ALIVE ACK missing count " },
{ "lost.reset", "RESET ACK missing count " },
};
static const struct rate_ctr_group_desc nsvc_ctrg_desc = {
.group_name_prefix = "ns.nsvc",
.group_description = "NSVC Peer Statistics",
.num_ctr = ARRAY_SIZE(nsvc_ctr_description),
.ctr_desc = nsvc_ctr_description,
.class_id = OSMO_STATS_CLASS_PEER,
};
enum ns_stat {
NS_STAT_ALIVE_DELAY,
};
static const struct osmo_stat_item_desc nsvc_stat_description[] = {
{ "alive.delay", "ALIVE reponse time ", "ms", 16, 0 },
};
static const struct osmo_stat_item_group_desc nsvc_statg_desc = {
.group_name_prefix = "ns.nsvc",
.group_description = "NSVC Peer Statistics",
.num_items = ARRAY_SIZE(nsvc_stat_description),
.item_desc = nsvc_stat_description,
.class_id = OSMO_STATS_CLASS_PEER,
};
#define CHECK_TX_RC(rc, nsvc) \
if (rc < 0) \
LOGP(DNS, LOGL_ERROR, "TX failed (%d) to peer %s\n", \
rc, gprs_ns_ll_str(nsvc));
struct msgb *gprs_ns_msgb_alloc(void)
{
struct msgb *msg = msgb_alloc_headroom(NS_ALLOC_SIZE, NS_ALLOC_HEADROOM,
"GPRS/NS");
if (!msg) {
LOGP(DNS, LOGL_ERROR, "Failed to allocate NS message of size %d\n",
NS_ALLOC_SIZE);
}
return msg;
}
/*! \brief Lookup struct gprs_nsvc based on NSVCI
* \param[in] nsi NS instance in which to search
* \param[in] nsvci NSVCI to be searched
* \returns gprs_nsvc of respective NSVCI
*/
struct gprs_nsvc *gprs_nsvc_by_nsvci(struct gprs_ns_inst *nsi, uint16_t nsvci)
{
struct gprs_nsvc *nsvc;
llist_for_each_entry(nsvc, &nsi->gprs_nsvcs, list) {
if (nsvc->nsvci == nsvci)
return nsvc;
}
return NULL;
}
/*! \brief Lookup struct gprs_nsvc based on NSEI
* \param[in] nsi NS instance in which to search
* \param[in] nsei NSEI to be searched
* \returns fi
|