aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/osmo-bts/pcu_if.h1
-rw-r--r--include/osmo-bts/pcuif_proto.h9
-rw-r--r--src/common/pcu_sock.c17
-rw-r--r--src/common/rsl.c55
4 files changed, 73 insertions, 9 deletions
diff --git a/include/osmo-bts/pcu_if.h b/include/osmo-bts/pcu_if.h
index 98efb570..6253c84c 100644
--- a/include/osmo-bts/pcu_if.h
+++ b/include/osmo-bts/pcu_if.h
@@ -15,6 +15,7 @@ int pcu_tx_rach_ind(struct gsm_bts *bts, int16_t qta, uint16_t ra, uint32_t fn,
int pcu_tx_time_ind(uint32_t fn);
int pcu_tx_pag_req(const uint8_t *identity_lv, uint8_t chan_needed);
int pcu_tx_pch_data_cnf(uint32_t fn, uint8_t *data, uint8_t len);
+int pcu_tx_susp_req(struct gsm_lchan *lchan, uint32_t tlli, const uint8_t *ra_id, uint8_t cause);
int pcu_sock_init(const char *path);
void pcu_sock_exit(void);
diff --git a/include/osmo-bts/pcuif_proto.h b/include/osmo-bts/pcuif_proto.h
index b06077c3..144fba68 100644
--- a/include/osmo-bts/pcuif_proto.h
+++ b/include/osmo-bts/pcuif_proto.h
@@ -12,6 +12,7 @@
#define PCU_IF_MSG_DATA_REQ 0x00 /* send data to given channel */
#define PCU_IF_MSG_DATA_CNF 0x01 /* confirm (e.g. transmission on PCH) */
#define PCU_IF_MSG_DATA_IND 0x02 /* receive data from given channel */
+#define PCU_IF_MSG_SUSP_REQ 0x03 /* BTS forwards GPRS SUSP REQ to PCU */
#define PCU_IF_MSG_RTS_REQ 0x10 /* ready to send request */
#define PCU_IF_MSG_DATA_CNF_DT 0x11 /* confirm (with direct tlli) */
#define PCU_IF_MSG_RACH_IND 0x22 /* receive RACH */
@@ -171,6 +172,13 @@ struct gsm_pcu_if_pag_req {
uint8_t identity_lv[9];
} __attribute__ ((packed));
+/* BTS tells PCU about a GPRS SUSPENSION REQUEST received on DCCH */
+struct gsm_pcu_if_susp_req {
+ uint32_t tlli;
+ uint8_t ra_id[6];
+ uint8_t cause;
+} __attribute__ ((packed));
+
struct gsm_pcu_if {
/* context based information */
uint8_t msg_type; /* message type */
@@ -182,6 +190,7 @@ struct gsm_pcu_if {
struct gsm_pcu_if_data data_cnf;
struct gsm_pcu_if_data_cnf_dt data_cnf_dt;
struct gsm_pcu_if_data data_ind;
+ struct gsm_pcu_if_susp_req susp_req;
struct gsm_pcu_if_rts_req rts_req;
struct gsm_pcu_if_rach_ind rach_ind;
struct gsm_pcu_if_txt_ind txt_ind;
diff --git a/src/common/pcu_sock.c b/src/common/pcu_sock.c
index 440f561d..d6946028 100644
--- a/src/common/pcu_sock.c
+++ b/src/common/pcu_sock.c
@@ -466,6 +466,23 @@ int pcu_tx_pch_data_cnf(uint32_t fn, uint8_t *data, uint8_t len)
return pcu_sock_send(&bts_gsmnet, msg);
}
+/* forward data from a RR GPRS SUSPEND REQ towards PCU */
+int pcu_tx_susp_req(struct gsm_lchan *lchan, uint32_t tlli, const uint8_t *ra_id, uint8_t cause)
+{
+ struct msgb *msg;
+ struct gsm_pcu_if *pcu_prim;
+
+ msg = pcu_msgb_alloc(PCU_IF_MSG_SUSP_REQ, lchan->ts->trx->bts->nr);
+ if (!msg)
+ return -ENOMEM;
+ pcu_prim = (struct gsm_pcu_if *) msg->data;
+ pcu_prim->u.susp_req.tlli = tlli;
+ memcpy(pcu_prim->u.susp_req.ra_id, ra_id, sizeof(pcu_prim->u.susp_req.ra_id));
+ pcu_prim->u.susp_req.cause = cause;
+
+ return pcu_sock_send(&bts_gsmnet, msg);
+}
+
static int pcu_rx_data_req(struct gsm_bts *bts, uint8_t msg_type,
const struct gsm_pcu_if_data *data_req)
{
diff --git a/src/common/rsl.c b/src/common/rsl.c
index f93ca50d..5287201e 100644
--- a/src/common/rsl.c
+++ b/src/common/rsl.c
@@ -29,6 +29,7 @@
#include <sys/types.h>
#include <arpa/inet.h>
+#include <osmocom/core/byteswap.h>
#include <osmocom/core/msgb.h>
#include <osmocom/core/talloc.h>
#include <osmocom/gsm/rsl.h>
@@ -36,6 +37,7 @@
#include <osmocom/gsm/gsm0808.h>
#include <osmocom/gsm/protocol/gsm_12_21.h>
#include <osmocom/gsm/protocol/gsm_08_58.h>
+#include <osmocom/gsm/protocol/gsm_04_08.h>
#include <osmocom/gsm/protocol/ipaccess.h>
#include <osmocom/trau/osmo_ortp.h>
@@ -2557,32 +2559,35 @@ static inline int rsl_link_id_is_sacch(uint8_t link_id)
return 0;
}
-static int rslms_is_meas_rep(struct msgb *msg)
+static int rslms_get_meas_msg_type(struct msgb *msg, bool rllh_link_id_is_sacch)
{
struct abis_rsl_common_hdr *rh = msgb_l2(msg);
struct abis_rsl_rll_hdr *rllh;
struct gsm48_hdr *gh;
if ((rh->msg_discr & 0xfe) != ABIS_RSL_MDISC_RLL)
- return 0;
+ return -1;
if (rh->msg_type != RSL_MT_UNIT_DATA_IND)
- return 0;
+ return -2;
rllh = msgb_l2(msg);
- if (rsl_link_id_is_sacch(rllh->link_id) == 0)
- return 0;
+ if (rsl_link_id_is_sacch(rllh->link_id) != rllh_link_id_is_sacch)
+ return -3;
gh = msgb_l3(msg);
if (gh->proto_discr != GSM48_PDISC_RR)
- return 0;
+ return -4;
+
+ return gh->msg_type;
+}
- switch (gh->msg_type) {
+static int rslms_is_meas_rep(struct msgb *msg)
+{
+ switch (rslms_get_meas_msg_type(msg, 1)) {
case GSM48_MT_RR_MEAS_REP:
case GSM48_MT_RR_EXT_MEAS_REP:
return 1;
- default:
- break;
}
/* FIXME: this does not cover the Bter frame format and the associated
@@ -2591,6 +2596,36 @@ static int rslms_is_meas_rep(struct msgb *msg)
return 0;
}
+static int rslms_is_gprs_susp_req(struct msgb *msg)
+{
+ return rslms_get_meas_msg_type(msg, 0) == GSM48_MT_RR_GPRS_SUSP_REQ;
+}
+
+/* TS 44.018 9.1.13b GPRS suspension request */
+static int handle_gprs_susp_req(struct msgb *msg)
+{
+ struct gsm48_hdr *gh = msgb_l3(msg);
+ struct gsm48_gprs_susp_req *gsr;
+ uint32_t tlli;
+ int rc;
+
+ if (!gh || msgb_l3len(msg) < sizeof(*gh)+sizeof(*gsr)) {
+ LOGP(DRSL, LOGL_NOTICE, "%s Short GPRS SUSPEND REQ received, ignoring\n", gsm_lchan_name(msg->lchan));
+ return -EINVAL;
+ }
+
+ gsr = (struct gsm48_gprs_susp_req *) gh->data;
+ tlli = osmo_ntohl(gsr->tlli);
+
+ LOGP(DRSL, LOGL_INFO, "%s Fwd GPRS SUSPEND REQ for TLLI=0x%08x to PCU\n",
+ gsm_lchan_name(msg->lchan), tlli);
+ rc = pcu_tx_susp_req(msg->lchan, tlli, gsr->ra_id, gsr->cause);
+
+ msgb_free(msg);
+
+ return rc;
+}
+
static inline uint8_t ms_to2rsl(const struct gsm_lchan *lchan, const struct lapdm_entity *le)
{
return (lchan->ms_t_offs >= 0) ? lchan->ms_t_offs : (lchan->p_offs - le->ta);
@@ -2731,6 +2766,8 @@ int lapdm_rll_tx_cb(struct msgb *msg, struct lapdm_entity *le, void *ctx)
rc = rsl_tx_meas_res(lchan, msgb_l3(msg), msgb_l3len(msg), le);
msgb_free(msg);
return rc;
+ } else if (rslms_is_gprs_susp_req(msg)) {
+ return handle_gprs_susp_req(msg);
} else {
LOGP(DRSL, LOGL_INFO, "%s Fwd RLL msg %s from LAPDm to A-bis\n",
gsm_lchan_name(lchan), rsl_msg_name(rh->msg_type));