summaryrefslogtreecommitdiffstats
path: root/openbsc/src
diff options
context:
space:
mode:
Diffstat (limited to 'openbsc/src')
-rw-r--r--openbsc/src/osmo-ganc/Makefile.am2
-rw-r--r--openbsc/src/osmo-ganc/ganc_data.c34
-rw-r--r--openbsc/src/osmo-ganc/ganc_data.h50
-rw-r--r--openbsc/src/osmo-ganc/ganc_server.c117
-rw-r--r--openbsc/src/osmo-ganc/main.c10
5 files changed, 197 insertions, 16 deletions
diff --git a/openbsc/src/osmo-ganc/Makefile.am b/openbsc/src/osmo-ganc/Makefile.am
index 1b8545107..067fc9e8c 100644
--- a/openbsc/src/osmo-ganc/Makefile.am
+++ b/openbsc/src/osmo-ganc/Makefile.am
@@ -4,7 +4,7 @@ AM_LDFLAGS = $(COVERAGE_LDFLAGS)
bin_PROGRAMS = osmo-ganc
-osmo_ganc_SOURCES = conn.c ganc_server.c main.c
+osmo_ganc_SOURCES = conn.c ganc_server.c ganc_data.c main.c
osmo_ganc_LDADD = $(top_builddir)/src/libcommon/libcommon.a \
$(LIBOSMOSCCP_LIBS) $(LIBOSMOCORE_LIBS) \
diff --git a/openbsc/src/osmo-ganc/ganc_data.c b/openbsc/src/osmo-ganc/ganc_data.c
new file mode 100644
index 000000000..dd6470a56
--- /dev/null
+++ b/openbsc/src/osmo-ganc/ganc_data.c
@@ -0,0 +1,34 @@
+
+#include "ganc_data.h"
+
+
+void ganc_bts_init(struct ganc_bts *bts, struct ganc_net *net)
+{
+ bts->net = net;
+ bts->location_area_code = 1;
+ bts->routing_area_code = 1;
+ bts->cell_identity = 1;
+ bts->arfcn = 871;
+ bts->bsic = 63;
+}
+
+void ganc_net_init(struct ganc_net *net)
+{
+ net->country_code = 1;
+ net->network_code = 1;
+
+ net->timer[TU3901] = 30; /* seconds */
+ net->timer[TU3902] = 30; /* seconds */
+ net->timer[TU3903] = 1; /* minute */
+ net->timer[TU3904] = 30; /* seconds */
+ net->timer[TU3905] = 10; /* seconds */
+ net->timer[TU3906] = 30; /* seconds */
+ net->timer[TU3907] = 30; /* seconds */
+ net->timer[TU3908] = 5; /* seconds */
+ net->timer[TU3910] = 10;
+ net->timer[TU3920] = 10;
+ net->timer[TU4001] = 10;
+ net->timer[TU4002] = 5; /* seconds */
+ net->timer[TU4003] = 5;
+ net->timer[T3212] = 1; /* 6 minutes */
+}
diff --git a/openbsc/src/osmo-ganc/ganc_data.h b/openbsc/src/osmo-ganc/ganc_data.h
index f67969c36..1c4a4c5e3 100644
--- a/openbsc/src/osmo-ganc/ganc_data.h
+++ b/openbsc/src/osmo-ganc/ganc_data.h
@@ -4,9 +4,59 @@
#include <osmocom/core/linuxlist.h>
#include "conn.h"
+struct ganc_bts;
+
struct gan_peer {
struct llist_head list;
struct osmo_conn *conn;
+ struct ganc_bts *bts;
+ uint8_t gan_release;
+};
+
+enum ganc_net_timer {
+ T3212,
+ TU3901,
+ TU3902,
+ TU3903,
+ TU3904,
+ TU3905,
+ TU3906,
+ TU3907,
+ TU3908,
+ //TU3909,
+ TU3910,
+ TU3920,
+ TU4001,
+ TU4002,
+ TU4003,
+ _NUM_GANC_TIMER
+};
+
+struct ganc_net {
+ uint8_t country_code;
+ uint8_t network_code;
+
+ uint16_t timer[_NUM_GANC_TIMER];
+
+ int emergency_gan_preferred;
+
+ struct {
+ int mode;
+ } gprs;
+};
+
+struct ganc_bts {
+ struct ganc_net *net;
+ uint16_t location_area_code;
+ uint16_t routing_area_code;
+ uint16_t cell_identity;
+ uint8_t bsic;
+ uint16_t arfcn;
};
+void ganc_net_init(struct ganc_net *net);
+void ganc_bts_init(struct ganc_bts *bts, struct ganc_net *net);
+
+extern struct ganc_bts *g_ganc_bts;
+
#endif
diff --git a/openbsc/src/osmo-ganc/ganc_server.c b/openbsc/src/osmo-ganc/ganc_server.c
index 3a937b239..fa3b5fb3a 100644
--- a/openbsc/src/osmo-ganc/ganc_server.c
+++ b/openbsc/src/osmo-ganc/ganc_server.c
@@ -15,6 +15,15 @@
#include "conn.h"
#include "ganc_data.h"
+static void push_rc_csr_hdr(struct msgb *msg, uint8_t pdisc, uint8_t msgt)
+{
+ struct gan_rc_csr_hdr *gh =
+ (struct gan_rc_csr_hdr *) msgb_push(msg, sizeof(*gh));
+
+ gh->pdisc = pdisc;
+ gh->msg_type = msgt;
+}
+
static struct msgb *unc_msgb_alloc(void)
{
return msgb_alloc_headroom(1024+128, 128, "GANC Tx");
@@ -27,28 +36,91 @@ static int unc_peer_tx(struct gan_peer *peer, struct msgb *msg)
/* compute and fill-in length */
msg->l2h = msg->data;
gh->len = htons(msgb_l2len(msg)-2);
+
+ if (peer->gan_release == 0) {
+ /* shomehow old pre-GAN UMA doesn't like RC */
+ if (gh->pdisc == GA_PDISC_RC)
+ gh->pdisc = GA_PDISC_CSR;
+ }
return osmo_conn_enqueue(peer->conn, msg);
}
+static uint8_t *msgb_tlv_be16_put(struct msgb *msg, uint8_t tag, uint16_t val)
+{
+ uint16_t _val = htons(val);
+ return msgb_tlv_put(msg, tag, 2, (uint8_t *) &_val);
+}
+
+static void build_gan_cch_desc(struct gan_cch_desc_ie *ie, struct ganc_bts *bts)
+{
+ struct ganc_net *net = bts->net;
+
+ ie->ecmc = 0; /* Early Classmark allowed */
+ ie->nmo = 0; /* NMO 1 */
+ if (net->gprs.mode != 0)
+ ie->gprs = 0;
+ else
+ ie->gprs = 1; /* No GPRS */
+ ie->dtm = 0; /* No Dual Transfer Mode */
+ ie->att = 1; /* IMSI attach/detach shall be used */
+ ie->mscr = 1; /* Release 99 onwards */
+ ie->t3212 = net->timer[T3212];
+ ie->rac = bts->routing_area_code;
+ ie->sgsnr = 1; /* Release 99 onwards */
+ ie->ecmp = net->emergency_gan_preferred;
+ ie->re = 1; /* No call re-esetablishment */
+ ie->pfcfm = 0; /* No PFC */
+ ie->tgecs = 1; /* Permit UTRAN classmark change */
+ if (!net->emergency_gan_preferred)
+ ie->access_class[0] |= 0x4; /* No emergency calls */
+}
+
+/* FIXME: move to libosmocore */
+static void gsm48_cell_desc(struct gsm48_cell_desc *cd, uint8_t bsic, uint16_t arfcn)
+{
+ cd->ncc = (bsic >> 3) & 0x07;
+ cd->bcc = bsic & 0x07;
+ cd->arfcn_hi = arfcn >> 8;
+ cd->arfcn_lo = arfcn & 0xff;
+}
+
static int tx_unc_reg_acc(struct gan_peer *peer)
{
struct msgb *msg = unc_msgb_alloc();
- struct gan_rc_csr_hdr *gh = (struct gan_rc_csr_hdr*) msg->data;
+ struct gsm48_loc_area_id lai;
+ struct gsm48_cell_desc cd;
+ struct gan_cch_desc_ie ie;
+ struct ganc_bts *bts = peer->bts;
+ struct ganc_net *net = bts->net;
+ uint8_t gan_band = 0x02; /* GSM 1800 */
+
+ printf("<- GA-RC REGISTER ACCEPT\n");
if (!msg)
return -ENOMEM;
- gh->pdisc = GA_PDISC_RC;
- gh->msg_type = GA_MT_RC_REGISTER_ACCEPT;
+ gsm48_cell_desc(&cd, bts->bsic, bts->arfcn);
+ gsm48_generate_lai(&lai, net->country_code, net->network_code,
+ bts->location_area_code);
+ build_gan_cch_desc(&ie, bts);
+
+ push_rc_csr_hdr(msg, GA_PDISC_RC, GA_MT_RC_REGISTER_ACCEPT);
+
+ msgb_tlv_be16_put(msg, GA_IE_GERAN_CELL_ID, bts->cell_identity);
+ msgb_tlv_put(msg, GA_IE_LAC, sizeof(lai), (uint8_t *) &lai);
+ msgb_tlv_put(msg, GA_IE_GANC_CTRL_CH_DESC, sizeof(ie), (uint8_t *) &ie);
+ msgb_tlv_be16_put(msg, GA_IE_TU3910_TIMER, net->timer[TU3910]);
+ msgb_tlv_be16_put(msg, GA_IE_TU3906_TIMER, net->timer[TU3906]);
+ msgb_tlv_put(msg, GA_IE_GAN_BAND, 1, &gan_band);
+ msgb_tlv_be16_put(msg, GA_IE_TU3920_TIMER, net->timer[TU3920]);
+ msgb_tlv_put(msg, GA_IE_GANC_CELL_DESC, sizeof(cd), (uint8_t *) &cd);
+
+ if (net->gprs.mode != 0) {
+ msgb_tlv_be16_put(msg, GA_IE_TU4001_TIMER, net->timer[TU4001]);
+ msgb_tlv_be16_put(msg, GA_IE_TU4003_TIMER, net->timer[TU4003]);
+ }
-#if 0
- msgb_tlv_put(msg, GA_IE_GERAN_CELL_ID,,);
- msgb_tlv_put(msg, GA_IE_LAC,,);
- msgb_tlv_put(msg, GA_IE_GANC_CTRL_CH_DESC,,);
- msgb_tlv_put(msg, GA_IE_TU3910_TIMER,,);
- msgb_tlv_put(msg, GA_IE_TU3906_TIMER,,);
-#endif
return unc_peer_tx(peer, msg);
}
@@ -56,13 +128,13 @@ static int tx_unc_disco_acc(struct gan_peer *peer, const char *segw_host,
const char *ganc_host)
{
struct msgb *msg = unc_msgb_alloc();
- struct gan_rc_csr_hdr *gh = (struct gan_rc_csr_hdr*) msg->data;
+
+ printf("<- GA-RC DISCOVERY ACCEPT\n");
if (!msg)
return -ENOMEM;
- gh->pdisc = GA_PDISC_RC;
- gh->msg_type = GA_MT_RC_DISCOVERY_ACCEPT;
+ push_rc_csr_hdr(msg, GA_PDISC_RC, GA_MT_RC_DISCOVERY_ACCEPT);
msgb_tlv_put(msg, GA_IE_DEF_SEGW_FQDN, strlen(segw_host)+1, (uint8_t *) segw_host);
msgb_tlv_put(msg, GA_IE_DEF_GANC_FQDN, strlen(ganc_host)+1, (uint8_t *) ganc_host);
@@ -74,8 +146,12 @@ static int rx_unc_discovery_req(struct gan_peer *peer, struct msgb *msg,
struct gan_rc_csr_hdr *gh)
{
struct tlv_parsed tp;
+ int rc;
- tlv_parse(&tp, &tvlv_att_def, gh->data, htons(gh->len), 0, 0);
+ printf("-> GA-RC DISCOVERY REQUEST\n");
+ rc = tlv_parse(&tp, &tvlv_att_def, gh->data, htons(gh->len), 0, 0);
+ if (rc < 0)
+ fprintf(stderr, "error %d during tlv_parse\n", rc);
if (TLVP_PRESENT(&tp, GA_IE_MI)) {
char mi_string[32];
@@ -86,7 +162,15 @@ static int rx_unc_discovery_req(struct gan_peer *peer, struct msgb *msg,
}
return tx_unc_disco_acc(peer, "segw.uma.sysmocom.de",
- "ganc.uma.sysmocom.de");
+ "laforge.gnumonks.org");
+}
+
+static int rx_unc_register_req(struct gan_peer *peer, struct msgb *msg,
+ struct gan_rc_csr_hdr *gh)
+{
+ printf("-> GA-RC REGISTER REQUEST\n");
+
+ return tx_unc_reg_acc(peer);
}
static int rx_unc_rc(struct gan_peer *peer, struct msgb *msg, struct gan_rc_csr_hdr *gh)
@@ -95,6 +179,7 @@ static int rx_unc_rc(struct gan_peer *peer, struct msgb *msg, struct gan_rc_csr_
case GA_MT_RC_DISCOVERY_REQUEST:
return rx_unc_discovery_req(peer, msg, gh);
case GA_MT_RC_REGISTER_REQUEST:
+ return rx_unc_register_req(peer, msg, gh);
case GA_MT_RC_DEREGISTER:
break;
}
@@ -165,6 +250,8 @@ static void unc_accept_cb(struct osmo_conn *conn)
struct gan_peer *peer = talloc_zero(conn, struct gan_peer);
printf("accepted connection\n");
+ /* FIXME: later we may have different BTS with different ARFCN/BSIC/... */
+ peer->bts = g_ganc_bts;
peer->conn = conn;
conn->priv = peer;
}
diff --git a/openbsc/src/osmo-ganc/main.c b/openbsc/src/osmo-ganc/main.c
index 882df6ab0..c6e5eb394 100644
--- a/openbsc/src/osmo-ganc/main.c
+++ b/openbsc/src/osmo-ganc/main.c
@@ -39,6 +39,8 @@
#include <openbsc/signal.h>
#include <openbsc/vty.h>
+#include "ganc_data.h"
+
static const char *config_file = "osmo-ganc.cfg";
static const char *rf_ctrl = NULL;
@@ -162,6 +164,9 @@ void gsm_net_update_ctype(struct gsm_network *network)
{
}
+struct ganc_bts *g_ganc_bts;
+struct ganc_net *g_ganc_net;
+
int main(int argc, char **argv)
{
struct osmo_msc_data *msc;
@@ -170,6 +175,11 @@ int main(int argc, char **argv)
tall_bsc_ctx = talloc_named_const(NULL, 1, "openbsc");
+ g_ganc_net = talloc_zero(tall_bsc_ctx, struct ganc_net);
+ ganc_net_init(g_ganc_net);
+ g_ganc_bts = talloc_zero(g_ganc_net, struct ganc_bts);
+ ganc_bts_init(g_ganc_bts, g_ganc_net);
+
osmo_init_logging(&log_info);
/* enable filters */