diff options
author | Andreas Eversberg <jolly@eversberg.eu> | 2013-06-12 09:18:48 +0200 |
---|---|---|
committer | Andreas Eversberg <jolly@eversberg.eu> | 2014-01-21 15:54:20 +0100 |
commit | e4154e44d197eeffbb516c0c1a2aaac81b1a81f6 (patch) | |
tree | 917a34b55eb72664ec6bce56d256143acf9cb68a | |
parent | bb30954a2954735fac4af0909ac6cb5b9a45cd70 (diff) |
Handover support to common part of BTS code
-rw-r--r-- | include/osmo-bts/handover.h | 8 | ||||
-rw-r--r-- | include/osmo-bts/logging.h | 1 | ||||
-rw-r--r-- | include/osmo-bts/rsl.h | 1 | ||||
-rw-r--r-- | src/common/Makefile.am | 2 | ||||
-rw-r--r-- | src/common/bts.c | 2 | ||||
-rw-r--r-- | src/common/handover.c | 138 | ||||
-rw-r--r-- | src/common/l1sap.c | 28 | ||||
-rw-r--r-- | src/common/logging.c | 7 | ||||
-rw-r--r-- | src/common/oml.c | 3 | ||||
-rw-r--r-- | src/common/rsl.c | 34 |
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); |