aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Eversberg <jolly@eversberg.eu>2013-06-12 09:18:48 +0200
committerAndreas Eversberg <jolly@eversberg.eu>2014-01-21 15:54:20 +0100
commite4154e44d197eeffbb516c0c1a2aaac81b1a81f6 (patch)
tree917a34b55eb72664ec6bce56d256143acf9cb68a
parentbb30954a2954735fac4af0909ac6cb5b9a45cd70 (diff)
Handover support to common part of BTS code
-rw-r--r--include/osmo-bts/handover.h8
-rw-r--r--include/osmo-bts/logging.h1
-rw-r--r--include/osmo-bts/rsl.h1
-rw-r--r--src/common/Makefile.am2
-rw-r--r--src/common/bts.c2
-rw-r--r--src/common/handover.c138
-rw-r--r--src/common/l1sap.c28
-rw-r--r--src/common/logging.c7
-rw-r--r--src/common/oml.c3
-rw-r--r--src/common/rsl.c34
10 files changed, 222 insertions, 2 deletions
diff --git a/include/osmo-bts/handover.h b/include/osmo-bts/handover.h
new file mode 100644
index 00000000..6d857744
--- /dev/null
+++ b/include/osmo-bts/handover.h
@@ -0,0 +1,8 @@
+#ifndef HANDOVER_H
+#define HANDOVER_H
+
+void handover_rach(struct gsm_bts_trx *trx, uint8_t chan_nr,
+ struct gsm_lchan *lchan, uint8_t ra, uint8_t acc_delay);
+void handover_frame(struct gsm_lchan *lchan);
+
+#endif /* HANDOVER_H */
diff --git a/include/osmo-bts/logging.h b/include/osmo-bts/logging.h
index bcb1fcb0..fda00fd6 100644
--- a/include/osmo-bts/logging.h
+++ b/include/osmo-bts/logging.h
@@ -17,6 +17,7 @@ enum {
DPCU,
DTRX,
DLOOP,
+ DHO,
DABIS,
DRTP,
DSUM,
diff --git a/include/osmo-bts/rsl.h b/include/osmo-bts/rsl.h
index cc39f813..6cb40dd2 100644
--- a/include/osmo-bts/rsl.h
+++ b/include/osmo-bts/rsl.h
@@ -23,6 +23,7 @@ int rsl_tx_chan_act_ack(struct gsm_lchan *lchan);
int rsl_tx_chan_act_nack(struct gsm_lchan *lchan, uint8_t cause);
int rsl_tx_conn_fail(struct gsm_lchan *lchan, uint8_t cause);
int rsl_tx_rf_rel_ack(struct gsm_lchan *lchan);
+int rsl_tx_hando_det(struct gsm_lchan *lchan, uint8_t *ho_delay);
/* call-back for LAPDm code, called when it wants to send msgs UP */
int lapdm_rll_tx_cb(struct msgb *msg, struct lapdm_entity *le, void *ctx);
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index 1c6ff9e2..acde056b 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -5,4 +5,4 @@ LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOTRAU_LIBS)
noinst_LIBRARIES = libbts.a
libbts_a_SOURCES = gsm_data_shared.c sysinfo.c logging.c abis.c oml.c bts.c \
rsl.c vty.c paging.c measurement.c amr.c lchan.c \
- load_indication.c pcu_sock.c l1sap.c
+ load_indication.c pcu_sock.c l1sap.c handover.c
diff --git a/src/common/bts.c b/src/common/bts.c
index 9e1d9549..47339230 100644
--- a/src/common/bts.c
+++ b/src/common/bts.c
@@ -74,6 +74,8 @@ int bts_init(struct gsm_bts *bts)
load_timer_start(bts);
btsb->rtp_jitter_buf_ms = 100;
btsb->max_ta = 63;
+ btsb->ny1 = 4;
+ btsb->t3105_ms = 300;
/* default RADIO_LINK_TIMEOUT */
btsb->radio_link_timeout = 32;
diff --git a/src/common/handover.c b/src/common/handover.c
new file mode 100644
index 00000000..3d0a5e98
--- /dev/null
+++ b/src/common/handover.c
@@ -0,0 +1,138 @@
+/* Paging message encoding + queue management */
+
+/* (C) 2012-2013 by Harald Welte <laforge@gnumonks.org>
+ * Andreas Eversberg <jolly@eversberg.eu>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <errno.h>
+
+#include <osmocom/gsm/protocol/gsm_04_08.h>
+#include <osmocom/gsm/rsl.h>
+
+#include <osmo-bts/bts.h>
+#include <osmo-bts/rsl.h>
+#include <osmo-bts/l1sap.h>
+#include <osmo-bts/logging.h>
+#include <osmo-bts/handover.h>
+
+/* Transmit a handover related PHYS INFO on given lchan */
+static int ho_tx_phys_info(struct gsm_lchan *lchan, uint8_t ta)
+{
+ struct msgb *msg = msgb_alloc_headroom(1024, 128, "PHYS INFO");
+ struct gsm48_hdr *gh;
+
+ if (!msg)
+ return -ENOMEM;
+
+ LOGP(DHO, LOGL_INFO, "Sending PHYSICAL INFORMATION to MS.\n");
+
+ /* Build RSL UNITDATA REQUEST message with 04.08 PHYS INFO */
+ msg->l3h = msg->data;
+ gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
+ gh->proto_discr = GSM48_PDISC_RR;
+ gh->msg_type = GSM48_MT_RR_HANDO_INFO;
+ msgb_put_u8(msg, ta);
+
+ rsl_rll_push_l3(msg, RSL_MT_UNIT_DATA_REQ, gsm_lchan2chan_nr(lchan),
+ 0x00, 0);
+
+ lapdm_rslms_recvmsg(msg, &lchan->lapdm_ch);
+}
+
+/* timer call-back for T3105 (handover PHYS INFO re-transmit) */
+static void ho_t3105_cb(void *data)
+{
+ struct gsm_lchan *lchan = data;
+ struct gsm_bts *bts = lchan->ts->trx->bts;
+ struct gsm_bts_role_bts *btsb = bts->role;
+
+ LOGP(DHO, LOGL_INFO, "T3105 timeout (%d resends left)\n",
+ btsb->ny1 - lchan->ho.phys_info_count);
+
+ if (lchan->state != LCHAN_S_ACTIVE) {
+ LOGP(DHO, LOGL_NOTICE, "NY1 reached, sending CONNection "
+ "FAILure to BSC.\n");
+ return;
+ }
+
+ if (lchan->ho.phys_info_count >= btsb->ny1) {
+ /* HO Abort */
+ rsl_tx_conn_fail(lchan, RSL_ERR_HANDOVER_ACC_FAIL);
+ return;
+ }
+
+ ho_tx_phys_info(lchan, lchan->rqd_ta);
+ lchan->ho.phys_info_count++;
+ osmo_timer_schedule(&lchan->ho.t3105, 0, btsb->t3105_ms * 1000);
+}
+
+/* received random access on dedicated channel */
+void handover_rach(struct gsm_bts_trx *trx, uint8_t chan_nr,
+ struct gsm_lchan *lchan, uint8_t ra, uint8_t acc_delay)
+{
+ struct gsm_bts *bts = trx->bts;
+ struct gsm_bts_role_bts *btsb = bts->role;
+
+ /* Ignore invalid handover ref */
+ if (lchan->ho.ref != ra) {
+ LOGP(DHO, LOGL_INFO, "RACH on decicated channel received, but "
+ "ra=0x%02x != expected ref=0x%02x. (This is no bug)\n",
+ ra, lchan->ho.ref);
+ return;
+ }
+
+ LOGP(DHO, LOGL_NOTICE, "RACH on decicated channel received with "
+ "TA=%u\n", acc_delay);
+
+ /* Set timing advance */
+ lchan->rqd_ta = acc_delay;
+
+ /* Stop handover detection, wait for valid frame */
+ lchan->ho.active = 2;
+ l1sap_chan_modify(trx, chan_nr);
+
+ /* Send HANDover DETect to BSC */
+ rsl_tx_hando_det(lchan, &acc_delay);
+
+ /* Send PHYS INFO */
+ lchan->ho.phys_info_count = 1;
+ ho_tx_phys_info(lchan, acc_delay);
+
+ /* Start T3105 */
+ LOGP(DHO, LOGL_DEBUG, "Starting T3105 with %u ms\n", btsb->t3105_ms);
+ lchan->ho.t3105.cb = ho_t3105_cb;
+ lchan->ho.t3105.data = lchan;
+ osmo_timer_schedule(&lchan->ho.t3105, 0, btsb->t3105_ms * 1000);
+}
+
+/* received frist valid data frame on dedicated channel */
+void handover_frame(struct gsm_lchan *lchan)
+{
+ LOGP(DHO, LOGL_INFO, "First valid frame detected\n");
+
+ /* Stop T3105 */
+ if (osmo_timer_pending(&lchan->ho.t3105))
+ osmo_timer_del(&lchan->ho.t3105);
+
+ /* Handover process is done */
+ lchan->ho.active = 0;
+}
+
diff --git a/src/common/l1sap.c b/src/common/l1sap.c
index daeba9c9..ea47cbc2 100644
--- a/src/common/l1sap.c
+++ b/src/common/l1sap.c
@@ -44,6 +44,7 @@
#include <osmo-bts/bts.h>
#include <osmo-bts/rsl.h>
#include <osmo-bts/bts_model.h>
+#include <osmo-bts/handover.h>
static int l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap);
@@ -701,6 +702,10 @@ static int l1sap_ph_data_ind(struct gsm_bts_trx *trx,
return -EINVAL;
}
+ /* report first valid received frame to handover process */
+ if (lchan->ho.active == 2)
+ handover_frame(lchan);
+
if (L1SAP_IS_LINK_SACCH(link_id)) {
radio_link_timeout(lchan, 0);
le = &lchan->lapdm_ch.lapdm_acch;
@@ -792,6 +797,25 @@ static int l1sap_tch_ind(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap,
return 0;
}
+/* special case where handover RACH is detected */
+static int l1sap_handover_rach(struct gsm_bts_trx *trx,
+ struct osmo_phsap_prim *l1sap, struct ph_rach_ind_param *rach_ind)
+{
+ struct gsm_lchan *lchan;
+ uint8_t chan_nr;
+ uint8_t tn, ss;
+
+ chan_nr = rach_ind->chan_nr;
+ tn = L1SAP_CHAN2TS(chan_nr);
+ ss = l1sap_chan2ss(chan_nr);
+ lchan = &trx->ts[tn].lchan[ss];
+
+ handover_rach(trx, chan_nr, lchan, rach_ind->ra, rach_ind->acc_delay);
+
+ /* must return 0, so in case of msg at l1sap, it will be freed */
+ return 0;
+}
+
/* RACH received from bts model */
static int l1sap_ph_rach_ind(struct gsm_bts_trx *trx,
struct osmo_phsap_prim *l1sap, struct ph_rach_ind_param *rach_ind)
@@ -811,6 +835,10 @@ static int l1sap_ph_rach_ind(struct gsm_bts_trx *trx,
return 0;
}
+ /* check for handover rach */
+ if (trx != bts->c0 && rach_ind->chan_nr != 0x88)
+ return l1sap_handover_rach(trx, l1sap, rach_ind);
+
/* check for packet access */
if (trx == bts->c0
&& L1SAP_IS_PACKET_RACH(rach_ind->ra)) {
diff --git a/src/common/logging.c b/src/common/logging.c
index 411a2dbe..d07c9ab2 100644
--- a/src/common/logging.c
+++ b/src/common/logging.c
@@ -58,6 +58,7 @@ static struct log_info_cat bts_log_info_cat[] = {
[DMEAS] = {
.name = "DMEAS",
.description = "Radio Measurement Processing",
+ .color = "\033[1;38m",
.enabled = 1, .loglevel = LOGL_NOTICE,
},
[DPAG] = {
@@ -113,6 +114,12 @@ static struct log_info_cat bts_log_info_cat[] = {
.color = "\033[0;34m",
.enabled = 1, .loglevel = LOGL_NOTICE,
},
+ [DHO] = {
+ .name = "DHO",
+ .description = "Handover",
+ .color = "\033[0;37m",
+ .enabled = 1, .loglevel = LOGL_NOTICE,
+ },
#if 0
[DNS] = {
.name = "DNS",
diff --git a/src/common/oml.c b/src/common/oml.c
index a381d1ae..573f898d 100644
--- a/src/common/oml.c
+++ b/src/common/oml.c
@@ -510,7 +510,8 @@ static int oml_rx_set_bts_attr(struct gsm_bts *bts, struct msgb *msg)
}
/* 9.4.10 BTS Air Timer */
- if (TLVP_PRESENT(&tp, NM_ATT_BTS_AIR_TIMER))
+ if (TLVP_PRESENT(&tp, NM_ATT_BTS_AIR_TIMER)
+ && *TLVP_VAL(&tp, NM_ATT_BTS_AIR_TIMER) > 0)
btsb->t3105_ms = *TLVP_VAL(&tp, NM_ATT_BTS_AIR_TIMER) * 10;
/* 9.4.37 NY1 */
diff --git a/src/common/rsl.c b/src/common/rsl.c
index be335e03..3d9c8f36 100644
--- a/src/common/rsl.c
+++ b/src/common/rsl.c
@@ -547,6 +547,28 @@ int rsl_tx_chan_act_ack(struct gsm_lchan *lchan)
return abis_bts_rsl_sendmsg(msg);
}
+/* 8.4.7 sending HANDOver DETection */
+int rsl_tx_hando_det(struct gsm_lchan *lchan, uint8_t *ho_delay)
+{
+ struct msgb *msg;
+ uint8_t chan_nr = gsm_lchan2chan_nr(lchan);
+
+ LOGP(DRSL, LOGL_INFO, "Sending HANDOver DETect\n");
+
+ msg = rsl_msgb_alloc(sizeof(struct abis_rsl_dchan_hdr));
+ if (!msg)
+ return -ENOMEM;
+
+ /* 9.3.17 Access Delay */
+ if (ho_delay)
+ msgb_tv_put(msg, RSL_IE_ACCESS_DELAY, *ho_delay);
+
+ rsl_dch_push_hdr(msg, RSL_MT_HANDO_DET, chan_nr);
+ msg->trx = lchan->ts->trx;
+
+ return abis_bts_rsl_sendmsg(msg);
+}
+
/* 8.4.3 sending CHANnel ACTIVation Negative ACK */
int rsl_tx_chan_act_nack(struct gsm_lchan *lchan, uint8_t cause)
{
@@ -715,6 +737,12 @@ static int rsl_rx_chan_activ(struct msgb *msg)
memset(&lchan->encr, 0, sizeof(lchan->encr));
/* 9.3.9 Handover Reference */
+ if ((type == RSL_ACT_INTER_ASYNC ||
+ type == RSL_ACT_INTER_SYNC) &&
+ TLVP_PRESENT(&tp, RSL_IE_HANDO_REF)) {
+ lchan->ho.active = 1;
+ lchan->ho.ref = *TLVP_VAL(&tp, RSL_IE_HANDO_REF);
+ }
/* 9.3.4 BS Power */
if (TLVP_PRESENT(&tp, RSL_IE_BS_POWER))
@@ -807,6 +835,12 @@ static int rsl_rx_rf_chan_rel(struct gsm_lchan *lchan, uint8_t chan_nr)
}
lchan->rel_act_kind = LCHAN_REL_ACT_RSL;
+
+ /* deactivate handover RACH detection and timer */
+ lchan->ho.active = 0;
+ if (osmo_timer_pending(&lchan->ho.t3105))
+ osmo_timer_del(&lchan->ho.t3105);
+
l1sap_chan_rel(lchan->ts->trx, chan_nr);
lapdm_channel_exit(&lchan->lapdm_ch);