aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAndreas Eversberg <jolly@eversberg.eu>2012-07-06 08:58:22 +0200
committerAndreas Eversberg <jolly@eversberg.eu>2012-07-06 08:58:22 +0200
commitbf5a0f6e2c9d0ae564b171b210f0f97bcbdddbf3 (patch)
tree519edcb8df656328b3fe28cc73ebd32002ab04e5 /src
parent81e895b6193530ea4b180c2118b9f40bb33de5b7 (diff)
Move BSSGP/NS instances creation and desctruction to gprs_bssgp_pcu.cpp
Diffstat (limited to 'src')
-rw-r--r--src/gprs_bssgp_pcu.cpp127
-rw-r--r--src/gprs_bssgp_pcu.h6
-rw-r--r--src/pcu_l1_if.cpp38
-rw-r--r--src/sysmo_l1_if.cpp12
4 files changed, 182 insertions, 1 deletions
diff --git a/src/gprs_bssgp_pcu.cpp b/src/gprs_bssgp_pcu.cpp
index 9084d841..c08cc8f2 100644
--- a/src/gprs_bssgp_pcu.cpp
+++ b/src/gprs_bssgp_pcu.cpp
@@ -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;
+}
+
diff --git a/src/gprs_bssgp_pcu.h b/src/gprs_bssgp_pcu.h
index 584bbc2f..30b1ff6a 100644
--- a/src/gprs_bssgp_pcu.h
+++ b/src/gprs_bssgp_pcu.h
@@ -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
diff --git a/src/pcu_l1_if.cpp b/src/pcu_l1_if.cpp
index 0652a1c6..ee126366 100644
--- a/src/pcu_l1_if.cpp
+++ b/src/pcu_l1_if.cpp
@@ -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);
+}
diff --git a/src/sysmo_l1_if.cpp b/src/sysmo_l1_if.cpp
index 89d7ab8c..a2dff87a 100644
--- a/src/sysmo_l1_if.cpp
+++ b/src/sysmo_l1_if.cpp
@@ -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);
}