aboutsummaryrefslogtreecommitdiffstats
path: root/src/osmo-bsc/lcs_loc_req.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/osmo-bsc/lcs_loc_req.c')
-rw-r--r--src/osmo-bsc/lcs_loc_req.c81
1 files changed, 56 insertions, 25 deletions
diff --git a/src/osmo-bsc/lcs_loc_req.c b/src/osmo-bsc/lcs_loc_req.c
index 5de3676fb..bb0c5e273 100644
--- a/src/osmo-bsc/lcs_loc_req.c
+++ b/src/osmo-bsc/lcs_loc_req.c
@@ -75,13 +75,13 @@ static const struct osmo_tdef_state_timeout lcs_loc_req_fsm_timeouts[32] = {
#define lcs_loc_req_fail(cause, fmt, args...) do { \
LOG_LCS_LOC_REQ(lcs_loc_req, LOGL_ERROR, "Perform Location Request failed in state %s: " fmt "\n", \
- osmo_fsm_inst_state_name(lcs_loc_req->fi), ## args); \
+ lcs_loc_req ? osmo_fsm_inst_state_name(lcs_loc_req->fi) : "NULL", ## args); \
lcs_loc_req->lcs_cause = (struct lcs_cause_ie){ \
.present = true, \
.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;
@@ -159,10 +180,7 @@ void lcs_loc_req_start(struct gsm_subscriber_connection *conn, struct msgb *loc_
lcs_loc_req = lcs_loc_req_alloc(conn->fi, GSCON_EV_LCS_LOC_REQ_END);
- *lcs_loc_req = (struct lcs_loc_req){
- .fi = lcs_loc_req->fi,
- .conn = conn,
- };
+ lcs_loc_req->conn = conn;
conn->lcs.loc_req = lcs_loc_req;
if (!parse_bssmap_perf_loc_req(lcs_loc_req, loc_req_msg))
@@ -193,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);
@@ -208,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,
@@ -219,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;
}
@@ -234,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);
@@ -303,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,
},
},
};
@@ -316,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 {
@@ -368,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);
@@ -460,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);
}
@@ -484,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)
@@ -501,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);
}