diff options
Diffstat (limited to 'src/osmo-bsc/lcs_loc_req.c')
-rw-r--r-- | src/osmo-bsc/lcs_loc_req.c | 74 |
1 files changed, 54 insertions, 20 deletions
diff --git a/src/osmo-bsc/lcs_loc_req.c b/src/osmo-bsc/lcs_loc_req.c index ca5c7b93f..bb0c5e273 100644 --- a/src/osmo-bsc/lcs_loc_req.c +++ b/src/osmo-bsc/lcs_loc_req.c @@ -81,7 +81,7 @@ static const struct osmo_tdef_state_timeout lcs_loc_req_fsm_timeouts[32] = { .cause_val = cause, \ }; \ lcs_loc_req_fsm_state_chg(lcs_loc_req->fi, LCS_LOC_REQ_ST_FAILED); \ - } while(0) + } while (0) static struct lcs_loc_req *lcs_loc_req_alloc(struct osmo_fsm_inst *parent_fi, uint32_t parent_event_term) { @@ -104,13 +104,13 @@ static bool parse_bssmap_perf_loc_req(struct lcs_loc_req *lcs_loc_req, struct ms { struct tlv_parsed tp_arr[1]; struct tlv_parsed *tp = &tp_arr[0]; - struct tlv_p_entry *e; + const struct tlv_p_entry *e; int payload_length; #define PARSE_ERR(ERRMSG) do { \ lcs_loc_req_fail(LCS_CAUSE_PROTOCOL_ERROR, "rx BSSMAP Perform Location Request: " ERRMSG); \ return false; \ - } while(0) + } while (0) payload_length = msg->tail - msg->l4h; if (tlv_parse2(tp_arr, 1, gsm0808_att_tlvdef(), msg->l4h + 1, payload_length - 1, 0, 0) <= 0) @@ -127,6 +127,29 @@ static bool parse_bssmap_perf_loc_req(struct lcs_loc_req *lcs_loc_req, struct ms lcs_loc_req->req.cell_id_present = true; } + /* 3GPP TS 49.031, section 10.14 (C) "LCS Client Type" */ + if (TLVP_PRES_LEN(tp, GSM0808_IE_LCS_CLIENT_TYPE, 1)) { + lcs_loc_req->req.client_type = *TLVP_VAL(tp, GSM0808_IE_LCS_CLIENT_TYPE); + lcs_loc_req->req.client_type_present = true; + } else if (lcs_loc_req->req.location_type.location_information == BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC) + PARSE_ERR("Missing LCS Client Type IE"); + + /* 3GPP TS 49.031, section 10.15 (O) "LCS Priority" */ + if (TLVP_PRES_LEN(tp, GSM0808_IE_LCS_PRIORITY, 1)) { + lcs_loc_req->req.priority = *TLVP_VAL(tp, GSM0808_IE_LCS_PRIORITY); + lcs_loc_req->req.priority_present = true; + } + + /* 3GPP TS 49.031, section 10.16 (C) "LCS QoS" */ + if (TLVP_PRES_LEN(tp, GSM0808_IE_LCS_QOS, sizeof(lcs_loc_req->req.qos))) { + size_t qos_len = TLVP_LEN(tp, GSM0808_IE_LCS_QOS); + if (qos_len > sizeof(lcs_loc_req->req.qos)) + qos_len = sizeof(lcs_loc_req->req.qos); + memcpy(&lcs_loc_req->req.qos, TLVP_VAL(tp, GSM0808_IE_LCS_QOS), qos_len); + lcs_loc_req->req.qos_present = true; + } else if (lcs_loc_req->req.location_type.location_information == BSSMAP_LE_LOC_INFO_CURRENT_GEOGRAPHIC) + PARSE_ERR("Missing LCS QoS IE"); + if ((e = TLVP_GET(tp, GSM0808_IE_IMSI))) { if (osmo_mobile_identity_decode(&lcs_loc_req->req.imsi, e->val, e->len, false) || lcs_loc_req->req.imsi.type != GSM_MI_TYPE_IMSI) @@ -139,8 +162,6 @@ static bool parse_bssmap_perf_loc_req(struct lcs_loc_req *lcs_loc_req, struct ms PARSE_ERR("Failed to parse IMEI IE"); } - // FIXME LCS QoS IE is mandatory for requesting the location - /* A lot of IEs remain ignored... */ return true; @@ -190,7 +211,7 @@ static int handle_bssmap_le_conn_oriented_info(struct lcs_loc_req *lcs_loc_req, { switch (bssmap_le->conn_oriented_info.apdu.msg_type) { case BSSLAP_MSGT_TA_REQUEST: - rate_ctr_inc(&bsc_gsmnet->smlc->ctrs->ctr[SMLC_CTR_BSSMAP_LE_RX_DT1_BSSLAP_TA_REQUEST]); + rate_ctr_inc(rate_ctr_group_get_ctr(bsc_gsmnet->smlc->ctrs, SMLC_CTR_BSSMAP_LE_RX_DT1_BSSLAP_TA_REQUEST)); LOG_LCS_LOC_REQ(lcs_loc_req, LOGL_DEBUG, "rx BSSLAP TA Request\n"); /* The TA Request message contains only the message type. */ return lcs_ta_req_start(lcs_loc_req); @@ -205,8 +226,8 @@ int lcs_loc_req_rx_bssmap_le(struct gsm_subscriber_connection *conn, struct msgb { struct lcs_loc_req *lcs_loc_req = conn->lcs.loc_req; struct bssap_le_pdu bssap_le; - struct osmo_bssap_le_err *err; - struct rate_ctr *ctr = bsc_gsmnet->smlc->ctrs->ctr; + struct osmo_bssap_le_err *err = NULL; + struct rate_ctr_group *ctrg = bsc_gsmnet->smlc->ctrs; if (!lcs_loc_req) { LOGPFSMSL(conn->fi, DLCS, LOGL_ERROR, @@ -216,13 +237,13 @@ int lcs_loc_req_rx_bssmap_le(struct gsm_subscriber_connection *conn, struct msgb if (osmo_bssap_le_dec(&bssap_le, &err, msg, msg)) { LOG_LCS_LOC_REQ(lcs_loc_req, LOGL_ERROR, "Rx BSSAP-LE message with error: %s\n", err->logmsg); - rate_ctr_inc(&ctr[SMLC_CTR_BSSMAP_LE_RX_DT1_ERR_INVALID_MSG]); + rate_ctr_inc(rate_ctr_group_get_ctr(ctrg, SMLC_CTR_BSSMAP_LE_RX_DT1_ERR_INVALID_MSG)); return -EINVAL; } if (bssap_le.discr != BSSAP_LE_MSG_DISCR_BSSMAP_LE) { LOG_LCS_LOC_REQ(lcs_loc_req, LOGL_ERROR, "Rx BSSAP-LE: discr %d not implemented\n", bssap_le.discr); - rate_ctr_inc(&ctr[SMLC_CTR_BSSMAP_LE_RX_DT1_ERR_INVALID_MSG]); + rate_ctr_inc(rate_ctr_group_get_ctr(ctrg, SMLC_CTR_BSSMAP_LE_RX_DT1_ERR_INVALID_MSG)); return -ENOTSUP; } @@ -231,9 +252,9 @@ int lcs_loc_req_rx_bssmap_le(struct gsm_subscriber_connection *conn, struct msgb switch (bssap_le.bssmap_le.msg_type) { case BSSMAP_LE_MSGT_PERFORM_LOC_RESP: if (bssap_le.bssmap_le.perform_loc_resp.location_estimate_present) - rate_ctr_inc(&ctr[SMLC_CTR_BSSMAP_LE_RX_DT1_PERFORM_LOCATION_RESPONSE_SUCCESS]); + rate_ctr_inc(rate_ctr_group_get_ctr(ctrg, SMLC_CTR_BSSMAP_LE_RX_DT1_PERFORM_LOCATION_RESPONSE_SUCCESS)); else - rate_ctr_inc(&ctr[SMLC_CTR_BSSMAP_LE_RX_DT1_PERFORM_LOCATION_RESPONSE_FAILURE]); + rate_ctr_inc(rate_ctr_group_get_ctr(ctrg, SMLC_CTR_BSSMAP_LE_RX_DT1_PERFORM_LOCATION_RESPONSE_FAILURE)); return osmo_fsm_inst_dispatch(lcs_loc_req->fi, LCS_LOC_REQ_EV_RX_LB_PERFORM_LOCATION_RESPONSE, &bssap_le.bssmap_le); @@ -300,6 +321,17 @@ static void lcs_loc_req_wait_loc_resp_onenter(struct osmo_fsm_inst *fi, uint32_t .cell_id = lcs_loc_req->req.cell_id, .imsi = lcs_loc_req->req.imsi, .imei = lcs_loc_req->req.imei, + + .lcs_client_type_present = lcs_loc_req->req.client_type_present, + .lcs_client_type = lcs_loc_req->req.client_type, + + .more_items = true, + + .lcs_priority_present = lcs_loc_req->req.priority_present, + .lcs_priority = lcs_loc_req->req.priority, + + .lcs_qos_present = lcs_loc_req->req.qos_present, + .lcs_qos = lcs_loc_req->req.qos, }, }, }; @@ -313,7 +345,7 @@ static void lcs_loc_req_wait_loc_resp_onenter(struct osmo_fsm_inst *fi, uint32_t plr.bssmap_le.perform_loc_req.apdu = (struct bsslap_pdu){ .msg_type = BSSLAP_MSGT_TA_LAYER3, .ta_layer3 = { - .ta = lchan->rqd_ta, + .ta = lchan->last_ta, }, }; } else { @@ -365,11 +397,14 @@ static void lcs_loc_req_handover_performed(struct lcs_loc_req *lcs_loc_req) .msg_type = BSSLAP_MSGT_RESET, .reset = { .cell_id = lchan->ts->trx->bts->cell_identity, - .ta = lchan->rqd_ta, + .ta = lchan->last_ta, .cause = BSSLAP_CAUSE_INTRA_BSS_HO, }, }; - gsm48_lchan2chan_desc(&apdu->reset.chan_desc, lchan); + if (gsm48_lchan2chan_desc(&apdu->reset.chan_desc, lchan, lchan->tsc, false)) { + lcs_loc_req_fail(LCS_CAUSE_SYSTEM_FAILURE, "Error encoding Channel Number"); + return; + } } lcs_loc_req_send(lcs_loc_req, &bsslap); @@ -457,9 +492,7 @@ static void lcs_loc_req_got_loc_resp_onenter(struct osmo_fsm_inst *fi, uint32_t LOG_LCS_LOC_REQ(lcs_loc_req, LOGL_ERROR, "Failed to send Perform Location Response (A-interface)\n"); else - rate_ctr_inc(&lcs_loc_req->conn->sccp.msc->msc_ctrs->ctr[ - plr.location_estimate_present ? MSC_CTR_BSSMAP_TX_DT1_PERFORM_LOCATION_RESPONSE_SUCCESS - : MSC_CTR_BSSMAP_TX_DT1_PERFORM_LOCATION_RESPONSE_FAILURE]); + rate_ctr_inc(rate_ctr_group_get_ctr(lcs_loc_req->conn->sccp.msc->msc_ctrs, plr.location_estimate_present ? MSC_CTR_BSSMAP_TX_DT1_PERFORM_LOCATION_RESPONSE_SUCCESS : MSC_CTR_BSSMAP_TX_DT1_PERFORM_LOCATION_RESPONSE_FAILURE)); } osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REGULAR, NULL); } @@ -481,7 +514,8 @@ static void lcs_loc_req_failed_onenter(struct osmo_fsm_inst *fi, uint32_t prev_s }; /* If we're paging this subscriber for LCS, stop paging. */ - paging_request_cancel(lcs_loc_req->conn->bsub, BSC_PAGING_FOR_LCS); + if (lcs_loc_req->conn->bsub) + paging_request_cancel(lcs_loc_req->conn->bsub, BSC_PAGING_FOR_LCS); /* Send Perform Location Abort to SMLC, only if we got started on the Lb */ if (lcs_loc_req->conn->lcs.lb.state == SUBSCR_SCCP_ST_CONNECTED) @@ -498,7 +532,7 @@ static void lcs_loc_req_failed_onenter(struct osmo_fsm_inst *fi, uint32_t prev_s LOG_LCS_LOC_REQ(lcs_loc_req, LOGL_ERROR, "Failed to send BSSMAP Perform Location Response (A-interface)\n"); else - rate_ctr_inc(&lcs_loc_req->conn->sccp.msc->msc_ctrs->ctr[MSC_CTR_BSSMAP_TX_DT1_PERFORM_LOCATION_RESPONSE_FAILURE]); + rate_ctr_inc(rate_ctr_group_get_ctr(lcs_loc_req->conn->sccp.msc->msc_ctrs, MSC_CTR_BSSMAP_TX_DT1_PERFORM_LOCATION_RESPONSE_FAILURE)); } osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REGULAR, NULL); } |