Port gbproxy to NS2
Since NS2 has a different abstraction we mock up the prim send/recv functions and don't test NS like the old tests did. Related: SYS#4998 Change-Id: Iecfd0408a35a11638d254c1db3c1d477b1a11524
This commit is contained in:
parent
5f573156e2
commit
951e133d17
|
@ -25,7 +25,8 @@ ns
|
|||
nse 666 nsvci 666
|
||||
nse 666 remote-role sgsn
|
||||
! nse 666 encapsulation framerelay-gre
|
||||
! nse 666 remote-ip 172.16.1.70
|
||||
nse 666 remote-ip 127.0.0.1
|
||||
nse 666 remote-port 23001
|
||||
! nse 666 fr-dlci 666
|
||||
timer tns-block 3
|
||||
timer tns-block-retries 3
|
||||
|
@ -35,6 +36,7 @@ ns
|
|||
timer tns-alive 3
|
||||
timer tns-alive-retries 10
|
||||
encapsulation udp local-port 23000
|
||||
encapsulation udp local-ip 127.0.0.1
|
||||
! encapsulation framerelay-gre enabled 1
|
||||
gbproxy
|
||||
sgsn nsei 666
|
||||
|
|
|
@ -3,9 +3,10 @@
|
|||
|
||||
|
||||
#include <osmocom/core/msgb.h>
|
||||
#include <osmocom/core/timer.h>
|
||||
#include <osmocom/gsm/gsm23003.h>
|
||||
|
||||
#include <osmocom/gprs/gprs_ns.h>
|
||||
#include <osmocom/gprs/gprs_ns2.h>
|
||||
#include <osmocom/vty/command.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
|
@ -95,7 +96,7 @@ struct gbproxy_config {
|
|||
uint16_t nsip_sgsn_nsei;
|
||||
|
||||
/* NS instance of libosmogb */
|
||||
struct gprs_ns_inst *nsi;
|
||||
struct gprs_ns2_inst *nsi;
|
||||
|
||||
/* Linked list of all Gb peers (except SGSN) */
|
||||
struct llist_head bts_peers;
|
||||
|
@ -236,13 +237,13 @@ int gb_ctrl_cmds_install(void);
|
|||
int gbproxy_init_config(struct gbproxy_config *cfg);
|
||||
|
||||
/* Main input function for Gb proxy */
|
||||
int gbprox_rcvmsg(struct gbproxy_config *cfg, struct msgb *msg, uint16_t nsei, uint16_t ns_bvci, uint16_t nsvci);
|
||||
int gbprox_rcvmsg(void *ctx, struct msgb *msg);
|
||||
|
||||
int gbprox_signal(unsigned int subsys, unsigned int signal,
|
||||
void *handler_data, void *signal_data);
|
||||
|
||||
/* Reset all persistent NS-VC's */
|
||||
int gbprox_reset_persistent_nsvcs(struct gprs_ns_inst *nsi);
|
||||
|
||||
int gprs_ns2_prim_cb(struct osmo_prim_hdr *oph, void *ctx);
|
||||
|
||||
void gbprox_reset(struct gbproxy_config *cfg);
|
||||
|
||||
|
|
242
src/gb_proxy.c
242
src/gb_proxy.c
|
@ -36,8 +36,9 @@
|
|||
#include <osmocom/core/rate_ctr.h>
|
||||
#include <osmocom/core/stats.h>
|
||||
|
||||
#include <osmocom/gprs/gprs_ns.h>
|
||||
#include <osmocom/gprs/gprs_ns2.h>
|
||||
#include <osmocom/gprs/gprs_bssgp.h>
|
||||
#include <osmocom/gprs/gprs_bssgp_bss.h>
|
||||
|
||||
#include <osmocom/gsm/gsm_utils.h>
|
||||
|
||||
|
@ -385,6 +386,8 @@ static int gbproxy_gsm48_to_peer(struct gbproxy_peer *peer,
|
|||
link_info->vu_gen_tx_bss = (link_info->vu_gen_tx_bss + 1) % 512;
|
||||
|
||||
gprs_push_bssgp_dl_unitdata(msg, link_info->tlli.current);
|
||||
msg->l3h = msg->data;
|
||||
|
||||
rc = gbprox_relay2peer(msg, peer, bvci);
|
||||
msgb_free(msg);
|
||||
return rc;
|
||||
|
@ -779,21 +782,23 @@ static int gbprox_relay2sgsn(struct gbproxy_config *cfg, struct msgb *old_msg,
|
|||
{
|
||||
/* create a copy of the message so the old one can
|
||||
* be free()d safely when we return from gbprox_rcvmsg() */
|
||||
struct gprs_ns2_inst *nsi = cfg->nsi;
|
||||
struct osmo_gprs_ns2_prim nsp = {};
|
||||
struct msgb *msg = bssgp_msgb_copy(old_msg, "msgb_relay2sgsn");
|
||||
int rc;
|
||||
|
||||
DEBUGP(DGPRS, "NSEI=%u proxying BTS->SGSN (NS_BVCI=%u, NSEI=%u)\n",
|
||||
msgb_nsei(msg), ns_bvci, sgsn_nsei);
|
||||
|
||||
msgb_bvci(msg) = ns_bvci;
|
||||
msgb_nsei(msg) = sgsn_nsei;
|
||||
nsp.bvci = ns_bvci;
|
||||
nsp.nsei = sgsn_nsei;
|
||||
|
||||
strip_ns_hdr(msg);
|
||||
|
||||
rc = gprs_ns_sendmsg(bssgp_nsi, msg);
|
||||
osmo_prim_init(&nsp.oph, SAP_NS, PRIM_NS_UNIT_DATA,
|
||||
PRIM_OP_REQUEST, msg);
|
||||
rc = gprs_ns2_recv_prim(nsi, &nsp.oph);
|
||||
if (rc < 0)
|
||||
rate_ctr_inc(&cfg->ctrg->ctr[GBPROX_GLOB_CTR_TX_ERR_SGSN]);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -803,19 +808,23 @@ static int gbprox_relay2peer(struct msgb *old_msg, struct gbproxy_peer *peer,
|
|||
{
|
||||
/* create a copy of the message so the old one can
|
||||
* be free()d safely when we return from gbprox_rcvmsg() */
|
||||
struct gprs_ns2_inst *nsi = peer->cfg->nsi;
|
||||
struct osmo_gprs_ns2_prim nsp = {};
|
||||
struct msgb *msg = bssgp_msgb_copy(old_msg, "msgb_relay2peer");
|
||||
int rc;
|
||||
|
||||
DEBUGP(DGPRS, "NSEI=%u proxying SGSN->BSS (NS_BVCI=%u, NSEI=%u)\n",
|
||||
msgb_nsei(msg), ns_bvci, peer->nsei);
|
||||
|
||||
msgb_bvci(msg) = ns_bvci;
|
||||
msgb_nsei(msg) = peer->nsei;
|
||||
nsp.bvci = ns_bvci;
|
||||
nsp.nsei = peer->nsei;
|
||||
|
||||
/* Strip the old NS header, it will be replaced with a new one */
|
||||
strip_ns_hdr(msg);
|
||||
|
||||
rc = gprs_ns_sendmsg(bssgp_nsi, msg);
|
||||
osmo_prim_init(&nsp.oph, SAP_NS, PRIM_NS_UNIT_DATA,
|
||||
PRIM_OP_REQUEST, msg);
|
||||
rc = gprs_ns2_recv_prim(nsi, &nsp.oph);
|
||||
if (rc < 0)
|
||||
rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_TX_ERR]);
|
||||
|
||||
|
@ -875,7 +884,7 @@ int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
|
|||
/* Receive an incoming PTP message from a BSS-side NS-VC */
|
||||
static int gbprox_rx_ptp_from_bss(struct gbproxy_config *cfg,
|
||||
struct msgb *msg, uint16_t nsei,
|
||||
uint16_t nsvci, uint16_t ns_bvci)
|
||||
uint16_t ns_bvci)
|
||||
{
|
||||
struct gbproxy_peer *peer;
|
||||
struct bssgp_normal_hdr *bgph = (struct bssgp_normal_hdr *) msgb_bssgph(msg);
|
||||
|
@ -885,9 +894,9 @@ static int gbprox_rx_ptp_from_bss(struct gbproxy_config *cfg,
|
|||
peer = gbproxy_peer_by_bvci(cfg, ns_bvci);
|
||||
if (!peer) {
|
||||
LOGP(DGPRS, LOGL_NOTICE, "Didn't find peer for "
|
||||
"BVCI=%u for PTP message from NSVC=%u/NSEI=%u (BSS), "
|
||||
"BVCI=%u for PTP message from NSEI=%u (BSS), "
|
||||
"discarding message\n",
|
||||
ns_bvci, nsvci, nsei);
|
||||
ns_bvci, nsei);
|
||||
return bssgp_tx_status(BSSGP_CAUSE_UNKNOWN_BVCI,
|
||||
&ns_bvci, msg);
|
||||
}
|
||||
|
@ -917,7 +926,7 @@ static int gbprox_rx_ptp_from_bss(struct gbproxy_config *cfg,
|
|||
/* Receive an incoming PTP message from a SGSN-side NS-VC */
|
||||
static int gbprox_rx_ptp_from_sgsn(struct gbproxy_config *cfg,
|
||||
struct msgb *msg, uint16_t nsei,
|
||||
uint16_t nsvci, uint16_t ns_bvci)
|
||||
uint16_t ns_bvci)
|
||||
{
|
||||
struct gbproxy_peer *peer;
|
||||
struct bssgp_normal_hdr *bgph = (struct bssgp_normal_hdr *) msgb_bssgph(msg);
|
||||
|
@ -929,8 +938,8 @@ static int gbprox_rx_ptp_from_sgsn(struct gbproxy_config *cfg,
|
|||
|
||||
if (!peer) {
|
||||
LOGP(DGPRS, LOGL_INFO, "Didn't find peer for "
|
||||
"BVCI=%u for message from NSVC=%u/NSEI=%u (SGSN)\n",
|
||||
ns_bvci, nsvci, nsei);
|
||||
"BVCI=%u for message from NSEI=%u (SGSN)\n",
|
||||
ns_bvci, nsei);
|
||||
rate_ctr_inc(&cfg->ctrg->
|
||||
ctr[GBPROX_GLOB_CTR_INV_BVCI]);
|
||||
return bssgp_tx_status(BSSGP_CAUSE_UNKNOWN_BVCI,
|
||||
|
@ -939,8 +948,8 @@ static int gbprox_rx_ptp_from_sgsn(struct gbproxy_config *cfg,
|
|||
|
||||
if (peer->blocked) {
|
||||
LOGP(DGPRS, LOGL_NOTICE, "Dropping PDU for "
|
||||
"blocked BVCI=%u via NSVC=%u/NSEI=%u\n",
|
||||
ns_bvci, nsvci, nsei);
|
||||
"blocked BVCI=%u via NSEI=%u\n",
|
||||
ns_bvci, nsei);
|
||||
rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_DROPPED]);
|
||||
return bssgp_tx_status(BSSGP_CAUSE_BVCI_BLOCKED, &ns_bvci, msg);
|
||||
}
|
||||
|
@ -1313,11 +1322,30 @@ static int gbproxy_is_sgsn_nsei(struct gbproxy_config *cfg, uint16_t nsei)
|
|||
(cfg->route_to_sgsn2 && nsei == cfg->nsip_sgsn2_nsei);
|
||||
}
|
||||
|
||||
/* Main input function for Gb proxy */
|
||||
int gbprox_rcvmsg(struct gbproxy_config *cfg, struct msgb *msg, uint16_t nsei,
|
||||
uint16_t ns_bvci, uint16_t nsvci)
|
||||
int gbprox_bssgp_send_cb(void *ctx, struct msgb *msg)
|
||||
{
|
||||
int rc;
|
||||
struct gbproxy_config *cfg = (struct gbproxy_config *) ctx;
|
||||
struct gprs_ns2_inst *nsi = cfg->nsi;
|
||||
struct osmo_gprs_ns2_prim nsp = {};
|
||||
|
||||
nsp.bvci = msgb_bvci(msg);
|
||||
nsp.nsei = msgb_nsei(msg);
|
||||
|
||||
osmo_prim_init(&nsp.oph, SAP_NS, PRIM_NS_UNIT_DATA, PRIM_OP_REQUEST, msg);
|
||||
rc = gprs_ns2_recv_prim(nsi, &nsp.oph);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Main input function for Gb proxy */
|
||||
int gbprox_rcvmsg(void *ctx, struct msgb *msg)
|
||||
{
|
||||
int rc;
|
||||
uint16_t nsei = msgb_nsei(msg);
|
||||
uint16_t ns_bvci = msgb_bvci(msg);
|
||||
struct gbproxy_config *cfg = (struct gbproxy_config *) ctx;
|
||||
|
||||
int remote_end_is_sgsn = gbproxy_is_sgsn_nsei(cfg, nsei);
|
||||
|
||||
/* Only BVCI=0 messages need special treatment */
|
||||
|
@ -1329,102 +1357,122 @@ int gbprox_rcvmsg(struct gbproxy_config *cfg, struct msgb *msg, uint16_t nsei,
|
|||
} else {
|
||||
/* All other BVCI are PTP */
|
||||
if (remote_end_is_sgsn)
|
||||
rc = gbprox_rx_ptp_from_sgsn(cfg, msg, nsei, nsvci,
|
||||
rc = gbprox_rx_ptp_from_sgsn(cfg, msg, nsei,
|
||||
ns_bvci);
|
||||
else
|
||||
rc = gbprox_rx_ptp_from_bss(cfg, msg, nsei, nsvci,
|
||||
rc = gbprox_rx_ptp_from_bss(cfg, msg, nsei,
|
||||
ns_bvci);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int gbprox_reset_persistent_nsvcs(struct gprs_ns_inst *nsi)
|
||||
{
|
||||
struct gprs_nsvc *nsvc;
|
||||
/* TODO: What about handling:
|
||||
* NS_AFF_CAUSE_VC_FAILURE,
|
||||
NS_AFF_CAUSE_VC_RECOVERY,
|
||||
NS_AFF_CAUSE_FAILURE,
|
||||
NS_AFF_CAUSE_RECOVERY,
|
||||
osmocom own causes
|
||||
NS_AFF_CAUSE_SNS_CONFIGURED,
|
||||
NS_AFF_CAUSE_SNS_FAILURE,
|
||||
*/
|
||||
|
||||
llist_for_each_entry(nsvc, &nsi->gprs_nsvcs, list) {
|
||||
if (!nsvc->persistent)
|
||||
continue;
|
||||
gprs_nsvc_reset(nsvc, NS_CAUSE_OM_INTERVENTION);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Signal handler for signals from NS layer */
|
||||
int gbprox_signal(unsigned int subsys, unsigned int signal,
|
||||
void *handler_data, void *signal_data)
|
||||
void gprs_ns_prim_status_cb(struct gbproxy_config *cfg, struct osmo_gprs_ns2_prim *nsp)
|
||||
{
|
||||
struct gbproxy_config *cfg = handler_data;
|
||||
struct ns_signal_data *nssd = signal_data;
|
||||
struct gprs_nsvc *nsvc = nssd->nsvc;
|
||||
/* TODO: bss nsei available/unavailable bssgp_tx_simple_bvci(BSSGP_PDUT_BVC_BLOCK, nsvc->nsei, peer->bvci, 0);
|
||||
* TODO: sgsn nsei available/unavailable
|
||||
*/
|
||||
struct gbproxy_peer *peer;
|
||||
int remote_end_is_sgsn = gbproxy_is_sgsn_nsei(cfg, nsvc->nsei);
|
||||
|
||||
if (subsys != SS_L_NS)
|
||||
return 0;
|
||||
switch (nsp->u.status.cause) {
|
||||
case NS_AFF_CAUSE_SNS_FAILURE:
|
||||
case NS_AFF_CAUSE_SNS_CONFIGURED:
|
||||
break;
|
||||
|
||||
if (signal == S_NS_RESET && remote_end_is_sgsn) {
|
||||
/* We have received a NS-RESET from the NSEI and NSVC
|
||||
* of the SGSN. This might happen with SGSN that start
|
||||
* their own NS-RESET procedure without waiting for our
|
||||
* NS-RESET */
|
||||
nsvc->remote_end_is_sgsn = 1;
|
||||
}
|
||||
case NS_AFF_CAUSE_RECOVERY:
|
||||
LOGP(DPCU, LOGL_NOTICE, "NS-NSE %d became available\n", nsp->nsei);
|
||||
if (nsp->nsei == cfg->nsip_sgsn_nsei) {
|
||||
/* look-up or create the BTS context for this BVC */
|
||||
struct bssgp_bvc_ctx *bctx = btsctx_by_bvci_nsei(nsp->bvci, nsp->nsei);
|
||||
if (!bctx)
|
||||
bctx = btsctx_alloc(nsp->bvci, nsp->nsei);
|
||||
|
||||
if (signal == S_NS_ALIVE_EXP && nsvc->remote_end_is_sgsn) {
|
||||
LOGP(DGPRS, LOGL_NOTICE, "Tns alive expired too often, "
|
||||
"re-starting RESET procedure\n");
|
||||
rate_ctr_inc(&cfg->ctrg->
|
||||
ctr[GBPROX_GLOB_CTR_RESTART_RESET_SGSN]);
|
||||
gprs_ns_nsip_connect(nsvc->nsi, &nsvc->ip.bts_addr,
|
||||
nsvc->nsei, nsvc->nsvci);
|
||||
}
|
||||
|
||||
if (!nsvc->remote_end_is_sgsn) {
|
||||
/* from BSS to SGSN */
|
||||
peer = gbproxy_peer_by_nsei(cfg, nsvc->nsei);
|
||||
if (!peer) {
|
||||
LOGP(DGPRS, LOGL_NOTICE, "signal '%s' for unknown peer NSEI=%u/NSVCI=%u\n",
|
||||
get_value_string(gprs_ns_signal_ns_names, signal), nsvc->nsei, nsvc->nsvci);
|
||||
return 0;
|
||||
bssgp_tx_bvc_reset_nsei_bvci(cfg->nsip_sgsn_nsei, 0, BSSGP_CAUSE_OML_INTERV, NULL, 0);
|
||||
}
|
||||
switch (signal) {
|
||||
case S_NS_RESET:
|
||||
case S_NS_BLOCK:
|
||||
if (!peer->blocked)
|
||||
break;
|
||||
LOGP(DGPRS, LOGL_NOTICE, "Converting '%s' from NSEI=%u/NSVCI=%u into BSSGP_BVC_BLOCK to SGSN\n",
|
||||
get_value_string(gprs_ns_signal_ns_names, signal), nsvc->nsei, nsvc->nsvci);
|
||||
bssgp_tx_simple_bvci(BSSGP_PDUT_BVC_BLOCK, nsvc->nsei,
|
||||
peer->bvci, 0);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* Forward this message to all NS-VC to BSS */
|
||||
struct gprs_ns_inst *nsi = cfg->nsi;
|
||||
struct gprs_nsvc *next_nsvc;
|
||||
|
||||
llist_for_each_entry(next_nsvc, &nsi->gprs_nsvcs, list) {
|
||||
if (next_nsvc->remote_end_is_sgsn)
|
||||
continue;
|
||||
|
||||
/* Note that the following does not start the full
|
||||
* procedures including timer based retransmissions. */
|
||||
switch (signal) {
|
||||
case S_NS_RESET:
|
||||
gprs_ns_tx_reset(next_nsvc, nssd->cause);
|
||||
break;
|
||||
case S_NS_BLOCK:
|
||||
gprs_ns_tx_block(next_nsvc, nssd->cause);
|
||||
break;
|
||||
case S_NS_UNBLOCK:
|
||||
gprs_ns_tx_unblock(next_nsvc);
|
||||
break;
|
||||
case NS_AFF_CAUSE_FAILURE:
|
||||
if (nsp->nsei == cfg->nsip_sgsn_nsei) {
|
||||
/* sgsn */
|
||||
/* TODO: BSVC: block all PtP towards bss */
|
||||
rate_ctr_inc(&cfg->ctrg->
|
||||
ctr[GBPROX_GLOB_CTR_RESTART_RESET_SGSN]);
|
||||
} else {
|
||||
/* bss became unavailable */
|
||||
peer = gbproxy_peer_by_nsei(cfg, nsp->nsei);
|
||||
if (!peer) {
|
||||
/* TODO: use primitive name + status cause name */
|
||||
LOGP(DGPRS, LOGL_NOTICE, "Received ns2 primitive %d for unknown peer NSEI=%u\n",
|
||||
nsp->u.status.cause, nsp->nsei);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!peer->blocked)
|
||||
break;
|
||||
bssgp_tx_simple_bvci(BSSGP_PDUT_BVC_BLOCK, cfg->nsip_sgsn_nsei,
|
||||
peer->bvci, 0);
|
||||
}
|
||||
LOGP(DPCU, LOGL_NOTICE, "NS-NSE %d became unavailable\n", nsp->nsei);
|
||||
break;
|
||||
default:
|
||||
LOGP(DPCU, LOGL_NOTICE,
|
||||
"NS: %s Unknown prim %d from NS\n",
|
||||
get_value_string(osmo_prim_op_names, nsp->oph.operation),
|
||||
nsp->oph.primitive);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* called by the ns layer */
|
||||
int gprs_ns2_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
|
||||
{
|
||||
struct osmo_gprs_ns2_prim *nsp;
|
||||
struct gbproxy_config *cfg = (struct gbproxy_config *) ctx;
|
||||
int rc = 0;
|
||||
|
||||
if (oph->sap != SAP_NS)
|
||||
return 0;
|
||||
|
||||
nsp = container_of(oph, struct osmo_gprs_ns2_prim, oph);
|
||||
|
||||
if (oph->operation != PRIM_OP_INDICATION) {
|
||||
LOGP(DPCU, LOGL_NOTICE, "NS: %s Unknown prim %d from NS\n",
|
||||
get_value_string(osmo_prim_op_names, oph->operation),
|
||||
oph->operation);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (oph->primitive) {
|
||||
case PRIM_NS_UNIT_DATA:
|
||||
/* hand the message into the BSSGP implementation */
|
||||
msgb_bssgph(oph->msg) = oph->msg->l3h;
|
||||
msgb_bvci(oph->msg) = nsp->bvci;
|
||||
msgb_nsei(oph->msg) = nsp->nsei;
|
||||
|
||||
rc = gbprox_rcvmsg(cfg, oph->msg);
|
||||
break;
|
||||
case PRIM_NS_STATUS:
|
||||
gprs_ns_prim_status_cb(cfg, nsp);
|
||||
break;
|
||||
default:
|
||||
LOGP(DPCU, LOGL_NOTICE,
|
||||
"NS: %s Unknown prim %d from NS\n",
|
||||
get_value_string(osmo_prim_op_names, oph->operation),
|
||||
oph->primitive);
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void gbprox_reset(struct gbproxy_config *cfg)
|
||||
|
|
|
@ -33,22 +33,41 @@
|
|||
|
||||
extern vector ctrl_node_vec;
|
||||
|
||||
static int ctrl_nsvc_state_cb(struct gprs_ns2_vc *nsvc, void *ctx) {
|
||||
/* FIXME: Can't get NSVC state in ns2
|
||||
struct ctrl_cmd *cmd = (struct ctrl_cmd *)ctx;
|
||||
|
||||
cmd->reply = gprs_ns2_vc_state_append(cmd->reply, nsvc);
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_nsvc_state(struct ctrl_cmd *cmd, void *data)
|
||||
{
|
||||
struct gbproxy_config *cfg = data;
|
||||
struct gprs_ns_inst *nsi = cfg->nsi;
|
||||
struct gprs_nsvc *nsvc;
|
||||
struct gprs_ns2_inst *nsi = cfg->nsi;
|
||||
struct gprs_ns2_nse *nse;
|
||||
struct gbproxy_peer *peer;
|
||||
|
||||
cmd->reply = talloc_strdup(cmd, "");
|
||||
|
||||
llist_for_each_entry(nsvc, &nsi->gprs_nsvcs, list) {
|
||||
if (nsvc == nsi->unknown_nsvc)
|
||||
continue;
|
||||
/* NS-VCs for SGSN */
|
||||
nse = gprs_ns2_nse_by_nsei(nsi, cfg->nsip_sgsn_nsei);
|
||||
if (nse)
|
||||
gprs_ns2_nse_foreach_nsvc(nse, &ctrl_nsvc_state_cb, cmd);
|
||||
/* NS-VCs for SGSN2 */
|
||||
nse = gprs_ns2_nse_by_nsei(nsi, cfg->nsip_sgsn2_nsei);
|
||||
if (nse)
|
||||
gprs_ns2_nse_foreach_nsvc(nse, &ctrl_nsvc_state_cb, cmd);
|
||||
|
||||
cmd->reply = gprs_nsvc_state_append(cmd->reply, nsvc);
|
||||
/* NS-VCs for BSS peers */
|
||||
llist_for_each_entry(peer, &cfg->bts_peers, list) {
|
||||
nse = gprs_ns2_nse_by_nsei(nsi, peer->nsei);
|
||||
if (nse)
|
||||
gprs_ns2_nse_foreach_nsvc(nse, &ctrl_nsvc_state_cb, cmd);
|
||||
}
|
||||
|
||||
return CTRL_CMD_REPLY;
|
||||
cmd->reply = "Getting NSVC state not yet implemented for NS2";
|
||||
return CTRL_CMD_ERROR;
|
||||
}
|
||||
|
||||
CTRL_CMD_DEFINE_RO(nsvc_state, "nsvc-state");
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
#include <osmocom/core/rate_ctr.h>
|
||||
#include <osmocom/core/stats.h>
|
||||
|
||||
#include <osmocom/gprs/gprs_ns.h>
|
||||
#include <osmocom/gprs/gprs_ns2.h>
|
||||
#include <osmocom/gprs/gprs_bssgp.h>
|
||||
|
||||
#include <osmocom/sgsn/signal.h>
|
||||
|
@ -80,26 +80,6 @@ static int daemonize = 0;
|
|||
/* Pointer to the SGSN peer */
|
||||
extern struct gbprox_peer *gbprox_peer_sgsn;
|
||||
|
||||
/* call-back function for the NS protocol */
|
||||
static int proxy_ns_cb(enum gprs_ns_evt event, struct gprs_nsvc *nsvc,
|
||||
struct msgb *msg, uint16_t bvci)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
switch (event) {
|
||||
case GPRS_NS_EVT_UNIT_DATA:
|
||||
rc = gbprox_rcvmsg(gbcfg, msg, nsvc->nsei, bvci, nsvc->nsvci);
|
||||
break;
|
||||
default:
|
||||
LOGP(DGPRS, LOGL_ERROR, "SGSN: Unknown event %u from NS\n", event);
|
||||
if (msg)
|
||||
msgb_free(msg);
|
||||
rc = -EIO;
|
||||
break;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void signal_handler(int signal)
|
||||
{
|
||||
fprintf(stdout, "signal %u received\n", signal);
|
||||
|
@ -269,6 +249,8 @@ static bool file_exists(const char *path)
|
|||
return stat(path, &sb) ? false : true;
|
||||
}
|
||||
|
||||
int gbprox_bssgp_send_cb(void *ctx, struct msgb *msg);
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int rc;
|
||||
|
@ -314,23 +296,23 @@ int main(int argc, char **argv)
|
|||
rate_ctr_init(tall_sgsn_ctx);
|
||||
osmo_stats_init(tall_sgsn_ctx);
|
||||
|
||||
bssgp_nsi = gprs_ns_instantiate(&proxy_ns_cb, tall_sgsn_ctx);
|
||||
if (!bssgp_nsi) {
|
||||
LOGP(DGPRS, LOGL_ERROR, "Unable to instantiate NS\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
gbcfg = talloc_zero(tall_sgsn_ctx, struct gbproxy_config);
|
||||
if (!gbcfg) {
|
||||
LOGP(DGPRS, LOGL_FATAL, "Unable to allocate config\n");
|
||||
exit(1);
|
||||
}
|
||||
gbproxy_init_config(gbcfg);
|
||||
gbcfg->nsi = bssgp_nsi;
|
||||
gprs_ns_vty_init(bssgp_nsi);
|
||||
gprs_ns_set_log_ss(DNS);
|
||||
gbcfg->nsi = gprs_ns2_instantiate(tall_sgsn_ctx, gprs_ns2_prim_cb, gbcfg);
|
||||
if (!gbcfg->nsi) {
|
||||
LOGP(DGPRS, LOGL_ERROR, "Unable to instantiate NS\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
gprs_ns2_vty_init(gbcfg->nsi, NULL);
|
||||
bssgp_set_log_ss(DBSSGP);
|
||||
osmo_signal_register_handler(SS_L_NS, &gbprox_signal, gbcfg);
|
||||
gprs_ns2_dynamic_create_nse(gbcfg->nsi, true);
|
||||
|
||||
bssgp_set_bssgp_callback(gbprox_bssgp_send_cb, gbcfg);
|
||||
|
||||
rc = gbproxy_parse_config(config_file, gbcfg);
|
||||
if (rc < 0) {
|
||||
|
@ -338,6 +320,8 @@ int main(int argc, char **argv)
|
|||
exit(2);
|
||||
}
|
||||
|
||||
gprs_ns2_vty_create();
|
||||
|
||||
/* start telnet after reading config for vty_get_bind_addr() */
|
||||
rc = telnet_init_dynif(tall_sgsn_ctx, NULL,
|
||||
vty_get_bind_addr(), OSMO_VTY_PORT_GBPROXY);
|
||||
|
@ -357,26 +341,13 @@ int main(int argc, char **argv)
|
|||
exit(1);
|
||||
}
|
||||
|
||||
if (!gprs_nsvc_by_nsei(gbcfg->nsi, gbcfg->nsip_sgsn_nsei)) {
|
||||
if (!gprs_ns2_nse_by_nsei(gbcfg->nsi, gbcfg->nsip_sgsn_nsei)) {
|
||||
LOGP(DGPRS, LOGL_FATAL, "You cannot proxy to NSEI %u "
|
||||
"without creating that NSEI before\n",
|
||||
gbcfg->nsip_sgsn_nsei);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
rc = gprs_ns_nsip_listen(bssgp_nsi);
|
||||
if (rc < 0) {
|
||||
LOGP(DGPRS, LOGL_FATAL, "Cannot bind/listen on NSIP socket\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
rc = gprs_ns_frgre_listen(bssgp_nsi);
|
||||
if (rc < 0) {
|
||||
LOGP(DGPRS, LOGL_FATAL, "Cannot bind/listen GRE "
|
||||
"socket. Do you have CAP_NET_RAW?\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
if (daemonize) {
|
||||
rc = osmo_daemonize();
|
||||
if (rc < 0) {
|
||||
|
@ -385,9 +356,6 @@ int main(int argc, char **argv)
|
|||
}
|
||||
}
|
||||
|
||||
/* Reset all the persistent NS-VCs that we've read from the config */
|
||||
gbprox_reset_persistent_nsvcs(bssgp_nsi);
|
||||
|
||||
while (1) {
|
||||
rc = osmo_select_main(0);
|
||||
if (rc < 0)
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <osmocom/gprs/gprs_msgb.h>
|
||||
#include <osmocom/sgsn/gb_proxy.h>
|
||||
|
||||
#include <osmocom/sgsn/gprs_utils.h>
|
||||
|
|
|
@ -26,10 +26,11 @@
|
|||
#include <inttypes.h>
|
||||
|
||||
#include <osmocom/core/talloc.h>
|
||||
#include <osmocom/core/timer.h>
|
||||
#include <osmocom/core/rate_ctr.h>
|
||||
#include <osmocom/gsm/gsm48.h>
|
||||
|
||||
#include <osmocom/gprs/gprs_ns.h>
|
||||
#include <osmocom/gprs/gprs_ns2.h>
|
||||
#include <osmocom/gsm/apn.h>
|
||||
|
||||
#include <osmocom/sgsn/debug.h>
|
||||
|
@ -666,27 +667,21 @@ DEFUN(delete_gb_nsei, delete_gb_nsei_cmd,
|
|||
}
|
||||
|
||||
if (delete_nsvc) {
|
||||
struct gprs_ns_inst *nsi = g_cfg->nsi;
|
||||
struct gprs_nsvc *nsvc, *nsvc2;
|
||||
struct gprs_ns2_inst *nsi = g_cfg->nsi;
|
||||
struct gprs_ns2_nse *nse;
|
||||
|
||||
counter = 0;
|
||||
llist_for_each_entry_safe(nsvc, nsvc2, &nsi->gprs_nsvcs, list) {
|
||||
if (nsvc->nsei != nsei)
|
||||
continue;
|
||||
if (nsvc->persistent)
|
||||
continue;
|
||||
|
||||
if (!dry_run)
|
||||
gprs_nsvc_delete(nsvc);
|
||||
else
|
||||
vty_out(vty, "NS-VC: NSEI %5u, NS-VCI %5u, "
|
||||
"remote %s%s",
|
||||
nsvc->nsei, nsvc->nsvci,
|
||||
gprs_ns_ll_str(nsvc), VTY_NEWLINE);
|
||||
counter += 1;
|
||||
nse = gprs_ns2_nse_by_nsei(nsi, nsei);
|
||||
if (!nse) {
|
||||
vty_out(vty, "NSEI not found%s", VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
vty_out(vty, "%sDeleted %d NS-VC%s",
|
||||
dry_run ? "Not " : "", counter, VTY_NEWLINE);
|
||||
|
||||
/* TODO: We should NOT delete a persistent NSEI/NSVC as soon as we can check for these */
|
||||
if (!dry_run)
|
||||
gprs_ns2_free_nse(nse);
|
||||
|
||||
vty_out(vty, "%sDeleted NS-VCs for NSEI %d%s",
|
||||
dry_run ? "Not " : "", nsei, VTY_NEWLINE);
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -95,7 +95,7 @@ class TestVTYGbproxy(TestVTYBase):
|
|||
|
||||
def testVtyShow(self):
|
||||
res = self.vty.command("show ns")
|
||||
self.assertTrue(res.find('Encapsulation NS-UDP-IP') >= 0)
|
||||
self.assertTrue(res.find('UDP bind') >= 0)
|
||||
|
||||
res = self.vty.command("show gbproxy stats")
|
||||
self.assertTrue(res.find('GBProxy Global Statistics') >= 0)
|
||||
|
@ -105,16 +105,14 @@ class TestVTYGbproxy(TestVTYBase):
|
|||
self.assertTrue(self.vty.verify('delete-gbproxy-peer 9999 bvci 7777', ['BVC not found']))
|
||||
res = self.vty.command("delete-gbproxy-peer 9999 all dry-run")
|
||||
self.assertTrue(res.find('Not Deleted 0 BVC') >= 0)
|
||||
self.assertTrue(res.find('Not Deleted 0 NS-VC') >= 0)
|
||||
self.assertTrue(res.find('NSEI not found') >= 0)
|
||||
res = self.vty.command("delete-gbproxy-peer 9999 only-bvc dry-run")
|
||||
self.assertTrue(res.find('Not Deleted 0 BVC') >= 0)
|
||||
self.assertTrue(res.find('Not Deleted 0 NS-VC') < 0)
|
||||
res = self.vty.command("delete-gbproxy-peer 9999 only-nsvc dry-run")
|
||||
self.assertTrue(res.find('Not Deleted 0 BVC') < 0)
|
||||
self.assertTrue(res.find('Not Deleted 0 NS-VC') >= 0)
|
||||
self.assertTrue(res.find('NSEI not found') >= 0)
|
||||
res = self.vty.command("delete-gbproxy-peer 9999 all")
|
||||
self.assertTrue(res.find('Deleted 0 BVC') >= 0)
|
||||
self.assertTrue(res.find('Deleted 0 NS-VC') >= 0)
|
||||
self.assertTrue(res.find('NSEI not found') >= 0)
|
||||
|
||||
class TestVTYSGSN(TestVTYBase):
|
||||
|
||||
|
|
Loading…
Reference in New Issue