diff options
author | Harald Welte <laforge@ganesha.gnumonks.org> | 2012-06-24 19:22:17 +0200 |
---|---|---|
committer | Harald Welte <laforge@ganesha.gnumonks.org> | 2012-06-24 19:22:17 +0200 |
commit | 83849feeb0311e0f96488c10aded1d0ff8f6e324 (patch) | |
tree | 0a9f129c3e76a667b32e57b53bf28229acca2270 /openbsc/src/osmo-ganc/ganc_server.c | |
parent | df4ea4f0e93b070af4b4c0e3566d62dc597d2e47 (diff) |
ganc: Correctly return DISCOVERY ACCEPT and REGISTRATION ACCEPT
Diffstat (limited to 'openbsc/src/osmo-ganc/ganc_server.c')
-rw-r--r-- | openbsc/src/osmo-ganc/ganc_server.c | 117 |
1 files changed, 102 insertions, 15 deletions
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; } |