ta: Create TimingAdvance class and make it belong to the BTS

This allows us to easily flush the state in case a PCU/BTS
connection is lost.
This commit is contained in:
Holger Hans Peter Freyther 2013-10-19 20:04:57 +02:00
parent d6ef5345e5
commit 111614a994
9 changed files with 77 additions and 30 deletions

1
TODO
View File

@ -7,3 +7,4 @@
* Replace trx/ts with pointers. E.g. a PDCH should know the trx * Replace trx/ts with pointers. E.g. a PDCH should know the trx
it is on... then we can omit trx, ts and parameters and just pass it is on... then we can omit trx, ts and parameters and just pass
the pdch. the pdch.
* On global free/reset... also flush the timing advance..

View File

@ -82,7 +82,8 @@ noinst_HEADERS = \
tbf.h \ tbf.h \
bts.h \ bts.h \
poll_controller.h \ poll_controller.h \
encoding.h encoding.h \
ta.h
osmo_pcu_SOURCES = pcu_main.cpp osmo_pcu_SOURCES = pcu_main.cpp

View File

@ -28,6 +28,7 @@ extern "C" {
} }
#include "poll_controller.h" #include "poll_controller.h"
#include "ta.h"
#endif #endif
#include <stdint.h> #include <stdint.h>
@ -122,6 +123,7 @@ public:
static BTS* main_bts(); static BTS* main_bts();
struct gprs_rlcmac_bts *bts_data(); struct gprs_rlcmac_bts *bts_data();
TimingAdvance *timing_advance();
/** TODO: change the number to unsigned */ /** TODO: change the number to unsigned */
void set_current_frame_number(int frame_number); void set_current_frame_number(int frame_number);
@ -134,6 +136,7 @@ private:
int m_cur_fn; int m_cur_fn;
struct gprs_rlcmac_bts m_bts; struct gprs_rlcmac_bts m_bts;
PollController m_pollController; PollController m_pollController;
TimingAdvance m_ta;
private: private:
/* disable copying to avoid slicing */ /* disable copying to avoid slicing */
@ -145,6 +148,11 @@ inline int BTS::current_frame_number() const
{ {
return m_cur_fn; return m_cur_fn;
} }
inline TimingAdvance *BTS::timing_advance()
{
return &m_ta;
}
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -161,12 +161,6 @@ int gprs_rlcmac_rcv_rts_block(struct gprs_rlcmac_bts *bts,
int gprs_rlcmac_imm_ass_cnf(uint8_t *data, uint32_t fn); int gprs_rlcmac_imm_ass_cnf(uint8_t *data, uint32_t fn);
int remember_timing_advance(uint32_t tlli, uint8_t ta);
int recall_timing_advance(uint32_t tlli);
int flush_timing_advance(void);
extern "C" { extern "C" {
#endif #endif
int alloc_algorithm_a(struct gprs_rlcmac_bts *bts, int alloc_algorithm_a(struct gprs_rlcmac_bts *bts,

View File

@ -397,14 +397,14 @@ int gprs_rlcmac_rcv_control_block(struct gprs_rlcmac_bts *bts,
"in packet ressource request of single " "in packet ressource request of single "
"block, but there is no resource request " "block, but there is no resource request "
"scheduled!\n"); "scheduled!\n");
rc = recall_timing_advance(tlli); rc = bts->bts->timing_advance()->recall(tlli);
if (rc >= 0) if (rc >= 0)
ta = rc; ta = rc;
else else
ta = 0; ta = 0;
} else { } else {
ta = sba->ta; ta = sba->ta;
remember_timing_advance(tlli, ta); bts->bts->timing_advance()->remember(tlli, ta);
llist_del(&sba->list); llist_del(&sba->list);
talloc_free(sba); talloc_free(sba);
} }
@ -452,7 +452,7 @@ int gprs_rlcmac_rcv_control_block(struct gprs_rlcmac_bts *bts,
"block, but there is no resource request " "block, but there is no resource request "
"scheduled!\n"); "scheduled!\n");
} else { } else {
remember_timing_advance(ul_control_block->u.Packet_Measurement_Report.TLLI, sba->ta); bts->bts->timing_advance()->remember(ul_control_block->u.Packet_Measurement_Report.TLLI, sba->ta);
llist_del(&sba->list); llist_del(&sba->list);
talloc_free(sba); talloc_free(sba);
} }
@ -820,7 +820,7 @@ int gprs_rlcmac_rcv_data_block_acknowledged(struct gprs_rlcmac_bts *bts,
/* mark TLLI valid now */ /* mark TLLI valid now */
tbf->tlli_valid = 1; tbf->tlli_valid = 1;
/* store current timing advance */ /* store current timing advance */
remember_timing_advance(tbf->tlli, tbf->ta); bts->bts->timing_advance()->remember(tbf->tlli, tbf->ta);
/* already have TLLI, but we stille get another one */ /* already have TLLI, but we stille get another one */
} else if (rh->ti) { } else if (rh->ti) {
uint32_t tlli; uint32_t tlli;

View File

@ -250,7 +250,7 @@ int main(int argc, char *argv[])
pcu_l1if_close(); pcu_l1if_close();
flush_timing_advance(); bts->bts->timing_advance()->flush();
talloc_report_full(tall_pcu_ctx, stderr); talloc_report_full(tall_pcu_ctx, stderr);
talloc_free(tall_pcu_ctx); talloc_free(tall_pcu_ctx);

View File

@ -19,6 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
#include <ta.h>
#include <gprs_rlcmac.h> #include <gprs_rlcmac.h>
extern "C" { extern "C" {
@ -36,22 +37,25 @@ extern void *tall_pcu_ctx;
/* enable to debug timing advance memory */ /* enable to debug timing advance memory */
//#define DEBUG_TA //#define DEBUG_TA
static LLIST_HEAD(gprs_rlcmac_ta_list);
static int gprs_rlcmac_ta_num = 0;
struct gprs_rlcmac_ta { struct gprs_rlcmac_ta {
struct llist_head list; struct llist_head list;
uint32_t tlli; uint32_t tlli;
uint8_t ta; uint8_t ta;
}; };
TimingAdvance::TimingAdvance()
: m_ta_len(0)
{
INIT_LLIST_HEAD(&m_ta_list);
}
/* remember timing advance of a given TLLI */ /* remember timing advance of a given TLLI */
int remember_timing_advance(uint32_t tlli, uint8_t ta) int TimingAdvance::remember(uint32_t tlli, uint8_t ta)
{ {
struct gprs_rlcmac_ta *ta_entry; struct gprs_rlcmac_ta *ta_entry;
/* check for existing entry */ /* check for existing entry */
llist_for_each_entry(ta_entry, &gprs_rlcmac_ta_list, list) { llist_for_each_entry(ta_entry, &m_ta_list, list) {
if (ta_entry->tlli == tlli) { if (ta_entry->tlli == tlli) {
#ifdef DEBUG_TA #ifdef DEBUG_TA
fprintf(stderr, "update %08x %d\n", tlli, ta); fprintf(stderr, "update %08x %d\n", tlli, ta);
@ -59,7 +63,7 @@ int remember_timing_advance(uint32_t tlli, uint8_t ta)
ta_entry->ta = ta; ta_entry->ta = ta;
/* relink to end of list */ /* relink to end of list */
llist_del(&ta_entry->list); llist_del(&ta_entry->list);
llist_add_tail(&ta_entry->list, &gprs_rlcmac_ta_list); llist_add_tail(&ta_entry->list, &m_ta_list);
return 0; return 0;
} }
} }
@ -68,12 +72,12 @@ int remember_timing_advance(uint32_t tlli, uint8_t ta)
fprintf(stderr, "remember %08x %d\n", tlli, ta); fprintf(stderr, "remember %08x %d\n", tlli, ta);
#endif #endif
/* if list is full, remove oldest entry */ /* if list is full, remove oldest entry */
if (gprs_rlcmac_ta_num == 30) { if (m_ta_len == 30) {
ta_entry = llist_entry(gprs_rlcmac_ta_list.next, ta_entry = llist_entry(m_ta_list.next,
struct gprs_rlcmac_ta, list); struct gprs_rlcmac_ta, list);
llist_del(&ta_entry->list); llist_del(&ta_entry->list);
talloc_free(ta_entry); talloc_free(ta_entry);
gprs_rlcmac_ta_num--; m_ta_len--;
} }
/* create new TA entry */ /* create new TA entry */
@ -83,18 +87,18 @@ int remember_timing_advance(uint32_t tlli, uint8_t ta)
ta_entry->tlli = tlli; ta_entry->tlli = tlli;
ta_entry->ta = ta; ta_entry->ta = ta;
llist_add_tail(&ta_entry->list, &gprs_rlcmac_ta_list); llist_add_tail(&ta_entry->list, &m_ta_list);
gprs_rlcmac_ta_num++; m_ta_len++;
return 0; return 0;
} }
int recall_timing_advance(uint32_t tlli) int TimingAdvance::recall(uint32_t tlli)
{ {
struct gprs_rlcmac_ta *ta_entry; struct gprs_rlcmac_ta *ta_entry;
uint8_t ta; uint8_t ta;
llist_for_each_entry(ta_entry, &gprs_rlcmac_ta_list, list) { llist_for_each_entry(ta_entry, &m_ta_list, list) {
if (ta_entry->tlli == tlli) { if (ta_entry->tlli == tlli) {
ta = ta_entry->ta; ta = ta_entry->ta;
#ifdef DEBUG_TA #ifdef DEBUG_TA
@ -110,13 +114,13 @@ int recall_timing_advance(uint32_t tlli)
return -EINVAL; return -EINVAL;
} }
int flush_timing_advance(void) int TimingAdvance::flush()
{ {
struct gprs_rlcmac_ta *ta_entry; struct gprs_rlcmac_ta *ta_entry;
int count = 0; int count = 0;
while (!llist_empty(&gprs_rlcmac_ta_list)) { while (!llist_empty(&m_ta_list)) {
ta_entry = llist_entry(gprs_rlcmac_ta_list.next, ta_entry = llist_entry(m_ta_list.next,
struct gprs_rlcmac_ta, list); struct gprs_rlcmac_ta, list);
#ifdef DEBUG_TA #ifdef DEBUG_TA
fprintf(stderr, "flush entry %08x %d\n", ta_entry->tlli, fprintf(stderr, "flush entry %08x %d\n", ta_entry->tlli,
@ -126,7 +130,7 @@ int flush_timing_advance(void)
talloc_free(ta_entry); talloc_free(ta_entry);
count++; count++;
} }
gprs_rlcmac_ta_num = 0; m_ta_len = 0;
return count; return count;
} }

39
src/ta.h Normal file
View File

@ -0,0 +1,39 @@
/*
* Copyright (C) 2012 Ivan Klyuchnikov
* Copyright (C) 2012 Andreas Eversberg <jolly@eversberg.eu>
* Copyright (C) 2013 by Holger Hans Peter Freyther
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* 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 General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#pragma once
extern "C" {
#include <osmocom/core/linuxlist.h>
}
#include <stdint.h>
class TimingAdvance {
public:
TimingAdvance();
int remember(uint32_t tlli, uint8_t ta);
int recall(uint32_t tlli);
int flush();
private:
size_t m_ta_len;
llist_head m_ta_list;
};

View File

@ -135,7 +135,7 @@ static int tbf_new_dl_assignment(struct gprs_rlcmac_bts *bts,
ta = tbf->ta; ta = tbf->ta;
else { else {
/* recall TA */ /* recall TA */
rc = recall_timing_advance(tlli); rc = bts->bts->timing_advance()->recall(tlli);
if (rc < 0) { if (rc < 0) {
LOGP(DRLCMAC, LOGL_NOTICE, "TA unknown" LOGP(DRLCMAC, LOGL_NOTICE, "TA unknown"
", assuming 0\n"); ", assuming 0\n");