diff options
author | Harald Welte <laforge@ganesha.gnumonks.org> | 2012-06-24 19:22:17 +0200 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2015-11-15 14:04:06 +0100 |
commit | 3aabc92f959897f4670294453a2b37a44b21c961 (patch) | |
tree | 3926438f38064d8acd1445f8e7b59207db2da98f /openbsc/src/osmo-ganc | |
parent | 88ec9c2b2f2d003b36b644185864ee6214a7babf (diff) |
ganc: Correctly return DISCOVERY ACCEPT and REGISTRATION ACCEPT
Diffstat (limited to 'openbsc/src/osmo-ganc')
-rw-r--r-- | openbsc/src/osmo-ganc/Makefile.am | 2 | ||||
-rw-r--r-- | openbsc/src/osmo-ganc/ganc_data.c | 34 | ||||
-rw-r--r-- | openbsc/src/osmo-ganc/ganc_data.h | 50 | ||||
-rw-r--r-- | openbsc/src/osmo-ganc/ganc_server.c | 117 | ||||
-rw-r--r-- | openbsc/src/osmo-ganc/main.c | 10 |
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 */ |