diff options
author | Andreas Eversberg <jolly@eversberg.eu> | 2012-07-06 08:58:22 +0200 |
---|---|---|
committer | Andreas Eversberg <jolly@eversberg.eu> | 2012-07-06 08:58:22 +0200 |
commit | bf5a0f6e2c9d0ae564b171b210f0f97bcbdddbf3 (patch) | |
tree | 519edcb8df656328b3fe28cc73ebd32002ab04e5 /src | |
parent | 81e895b6193530ea4b180c2118b9f40bb33de5b7 (diff) |
Move BSSGP/NS instances creation and desctruction to gprs_bssgp_pcu.cpp
Diffstat (limited to 'src')
-rw-r--r-- | src/gprs_bssgp_pcu.cpp | 127 | ||||
-rw-r--r-- | src/gprs_bssgp_pcu.h | 6 | ||||
-rw-r--r-- | src/pcu_l1_if.cpp | 38 | ||||
-rw-r--r-- | src/sysmo_l1_if.cpp | 12 |
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); } |