Move BSSGP/NS instances creation and desctruction to gprs_bssgp_pcu.cpp

This commit is contained in:
Andreas Eversberg 2012-07-06 08:58:22 +02:00
parent 81e895b619
commit bf5a0f6e2c
4 changed files with 182 additions and 1 deletions

View File

@ -24,6 +24,8 @@
struct sgsn_instance *sgsn;
void *tall_bsc_ctx;
struct bssgp_bvc_ctx *bctx = btsctx_alloc(BVCI, NSEI);
struct gprs_nsvc *nsvc = NULL;
extern uint16_t spoof_mcc, spoof_mnc;
int gprs_bssgp_pcu_rx_dl_ud(struct msgb *msg, struct tlv_parsed *tp)
{
@ -284,3 +286,128 @@ int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
{
return 0;
}
static int sgsn_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:
/* hand the message into the BSSGP implementation */
rc = gprs_bssgp_pcu_rcvmsg(msg);
break;
default:
LOGP(DPCU, LOGL_ERROR, "RLCMAC: Unknown event %u from NS\n", event);
if (msg)
talloc_free(msg);
rc = -EIO;
break;
}
return rc;
}
static int nsvc_unblocked = 0;
static int nsvc_signal_cb(unsigned int subsys, unsigned int signal,
void *handler_data, void *signal_data)
{
struct ns_signal_data *nssd;
if (subsys != SS_L_NS)
return -EINVAL;
nssd = (struct ns_signal_data *)signal_data;
if (nssd->nsvc != nsvc) {
LOGP(DPCU, LOGL_ERROR, "Signal received of unknown NSVC\n");
return -EINVAL;
}
switch (signal) {
case S_NS_UNBLOCK:
if (!nsvc_unblocked) {
nsvc_unblocked = 1;
LOGP(DPCU, LOGL_NOTICE, "NS-VC is unblocked.\n");
bssgp_tx_bvc_reset(bctx, bctx->bvci,
BSSGP_CAUSE_PROTO_ERR_UNSPEC);
}
break;
case S_NS_BLOCK:
if (nsvc_unblocked) {
nsvc_unblocked = 0;
LOGP(DPCU, LOGL_NOTICE, "NS-VC is blocked.\n");
}
break;
}
return 0;
}
/* create BSSGP/NS layer instances */
int gprs_bssgp_create(uint32_t sgsn_ip, uint16_t sgsn_port, uint16_t nsei,
uint16_t nsvci, uint16_t bvci, uint16_t mcc, uint16_t mnc, uint16_t lac,
uint16_t rac, uint16_t cell_id)
{
struct sockaddr_in dest;
if (bctx)
return 0; /* if already created, must return 0: no error */
bssgp_nsi = gprs_ns_instantiate(&sgsn_ns_cb, NULL);
if (!bssgp_nsi) {
LOGP(DBSSGP, LOGL_NOTICE, "Failed to create NS instance\n");
return -EINVAL;
}
gprs_ns_nsip_listen(bssgp_nsi);
dest.sin_family = AF_INET;
dest.sin_port = htons(sgsn_port);
dest.sin_addr.s_addr = htonl(sgsn_ip);
nsvc = gprs_ns_nsip_connect(bssgp_nsi, &dest, nsei, nsvci);
if (!nsvc) {
LOGP(DBSSGP, LOGL_NOTICE, "Failed to create NSVCt\n");
gprs_ns_destroy(bssgp_nsi);
bssgp_nsi = NULL;
return -EINVAL;
}
bctx = btsctx_alloc(bvci, nsei);
if (!bctx) {
LOGP(DBSSGP, LOGL_NOTICE, "Failed to create BSSGP context\n");
nsvc = NULL;
gprs_ns_destroy(bssgp_nsi);
bssgp_nsi = NULL;
return -EINVAL;
}
bctx->ra_id.mcc = spoof_mcc ? : mcc;
bctx->ra_id.mnc = spoof_mnc ? : mnc;
bctx->ra_id.lac = lac;
bctx->ra_id.rac = rac;
bctx->cell_id = cell_id;
osmo_signal_register_handler(SS_L_NS, nsvc_signal_cb, NULL);
// bssgp_tx_bvc_reset(bctx, bctx->bvci, BSSGP_CAUSE_PROTO_ERR_UNSPEC);
return 0;
}
void gprs_bssgp_destroy(void)
{
if (!bssgp_nsi)
return;
osmo_signal_unregister_handler(SS_L_NS, nsvc_signal_cb, NULL);
nsvc = NULL;
/* FIXME: move this to libgb: btsctx_free() */
llist_del(&bctx->list);
talloc_free(bctx);
bctx = NULL;
/* FIXME: blocking... */
gprs_ns_destroy(bssgp_nsi);
bssgp_nsi = NULL;
}

View File

@ -67,4 +67,10 @@ int gprs_bssgp_pcu_rx_sign(struct msgb *msg, struct tlv_parsed *tp, struct bssgp
int gprs_bssgp_pcu_rcvmsg(struct msgb *msg);
int gprs_bssgp_create(uint32_t sgsn_ip, uint16_t sgsn_port, uint16_t nsei,
uint16_t nsvci, uint16_t bvci, uint16_t mcc, uint16_t mnc, uint16_t lac,
uint16_t rac, uint16_t cell_id);
void gprs_bssgp_destroy(void);
#endif // GPRS_BSSGP_PCU_H

View File

@ -20,12 +20,13 @@
#include <errno.h>
#include <string.h>
#include <gprs_rlcmac.h>
#include <gprs_bssgp_pcu.h>
#include <pcu_l1_if.h>
#include <gprs_debug.h>
#include <bitvector.h>
#include <gsmL1prim.h>
#include <sys/socket.h>
#include <linux/in.h>
#include <arpa/inet.h>
extern "C" {
#include <osmocom/core/talloc.h>
#include <osmocom/core/write_queue.h>
@ -279,12 +280,40 @@ static int udp_write_cb(struct osmo_fd *ofd, struct msgb *msg)
return 0;
}
// TODO: We should move this parameters to config file.
#define SGSN_IP 127.0.0.1
#define SGSN_PORT 23000
#define NSEI 3
#define NSVCI 4
#define BVCI 7
#define MAX_LEN_PDU 60
#define IE_LLC_PDU 14
#define BLOCK_DATA_LEN 20
#define BLOCK_LEN 23
#define CELL_ID 0
#define MNC 2
#define MCC 262
#define PCU_LAC 1
#define PCU_RAC 0
int pcu_l1if_open()
{
//struct l1fwd_hdl *l1fh;
struct femtol1_hdl *fl1h;
int rc;
struct sockaddr_in dest;
dest.sin_family = AF_INET;
dest.sin_port = htons(SGSN_PORT);
inet_aton(SGSN_IP, &dest.sin_addr);
rc = gprs_bssgp_create(ntohl(dest.sin_addr.s_addr), SGSN_PORT, NSEI, NSVCI, BVCI, MCC, MNC, PCU_LAC, PCU_RAC, CELL_ID);
if (rc < 0)
return rc;
/* allocate new femtol1_handle */
fl1h = talloc_zero(NULL, struct femtol1_hdl);
INIT_LLIST_HEAD(&fl1h->wlc_list);
@ -318,3 +347,10 @@ int pcu_l1if_open()
return 0;
}
void pcu_l1if_close(void)
{
gprs_bssgp_destroy();
/* FIXME: cleanup l1if */
talloc_free(fl1h);
}

View File

@ -255,6 +255,7 @@ bssgp_failed:
}
}
}
gprs_bssgp_destroy();
return 0;
}
LOGP(DL1IF, LOGL_INFO, "BTS available\n");
@ -305,6 +306,15 @@ bssgp_failed:
LOGP(DL1IF, LOGL_INFO, " remote_port=%d\n", info_ind->remote_port[0]);
LOGP(DL1IF, LOGL_INFO, " remote_ip=%d\n", info_ind->remote_ip[0]);
rc = gprs_bssgp_create(info_ind->remote_ip[0], info_ind->remote_port[0],
info_ind->nsei, info_ind->nsvci[0], info_ind->bvci,
info_ind->mcc, info_ind->mnc, info_ind->lac, info_ind->rac,
info_ind->cell_id);
if (rc < 0) {
LOGP(DL1IF, LOGL_NOTICE, "SGSN not available\n");
goto bssgp_failed;
}
bts->cs1 = !!(info_ind->flags & PCU_IF_FLAG_CS1);
bts->cs2 = !!(info_ind->flags & PCU_IF_FLAG_CS2);
bts->cs3 = !!(info_ind->flags & PCU_IF_FLAG_CS3);
@ -484,6 +494,8 @@ static void pcu_sock_close(struct pcu_sock_state *state)
}
}
gprs_bssgp_destroy();
state->timer.cb = pcu_sock_timeout;
osmo_timer_schedule(&state->timer, 5, 0);
}