aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPau Espin Pedrol <pespin@sysmocom.de>2022-10-26 19:44:07 +0200
committerPau Espin Pedrol <pespin@sysmocom.de>2022-10-27 13:52:59 +0200
commit14beef6cfe93cc4e03643aaf698217be9b849a6e (patch)
tree6a89d6f5145d85eb9c1f5a32feb8136614bc3a38 /src
parentd6bb6190d3731d2c0fd620e8ac061bd5bb20b5dc (diff)
Move LLC enqueuing and retransmit timer to MS object
The LLC queue is already in the MS object. The LLC timer and most of the logic to enqueue its data is independent from the TBF. Change-Id: I56b89fcac838d8eb732b629734d5e458e9c806d1
Diffstat (limited to 'src')
-rw-r--r--src/gprs_ms.c52
-rw-r--r--src/gprs_ms.h3
-rw-r--r--src/tbf.cpp5
-rw-r--r--src/tbf.h1
-rw-r--r--src/tbf_dl.cpp61
-rw-r--r--src/tbf_dl.h7
6 files changed, 71 insertions, 58 deletions
diff --git a/src/gprs_ms.c b/src/gprs_ms.c
index d68f8aaa..f552d938 100644
--- a/src/gprs_ms.c
+++ b/src/gprs_ms.c
@@ -86,6 +86,21 @@ static void ms_release_timer_cb(void *data)
}
}
+static void ms_llc_timer_cb(void *_ms)
+{
+ struct GprsMs *ms = _ms;
+ struct gprs_rlcmac_dl_tbf *dl_tbf = ms_dl_tbf(ms);
+
+ if (!dl_tbf)
+ return;
+ if (tbf_state((const struct gprs_rlcmac_tbf *)dl_tbf) != TBF_ST_FLOW)
+ return;
+
+ LOGPTBFDL((const struct gprs_rlcmac_tbf *)dl_tbf, LOGL_DEBUG, "LLC receive timeout, requesting DL ACK\n");
+
+ tbf_dl_request_dl_ack(dl_tbf);
+}
+
static int ms_talloc_destructor(struct GprsMs *ms);
struct GprsMs *ms_alloc(struct gprs_rlcmac_bts *bts, uint32_t tlli)
{
@@ -113,6 +128,8 @@ struct GprsMs *ms_alloc(struct gprs_rlcmac_bts *bts, uint32_t tlli)
ms->imsi[0] = '\0';
osmo_timer_setup(&ms->timer, ms_release_timer_cb, NULL);
llc_queue_init(&ms->llc_queue, ms);
+ memset(&ms->llc_timer, 0, sizeof(ms->llc_timer));
+ osmo_timer_setup(&ms->llc_timer, ms_llc_timer_cb, ms);
ms_set_mode(ms, GPRS);
@@ -160,6 +177,7 @@ static int ms_talloc_destructor(struct GprsMs *ms)
}
llc_queue_clear(&ms->llc_queue, ms->bts);
+ osmo_timer_del(&ms->llc_timer);
if (ms->ctrs)
rate_ctr_group_free(ms->ctrs);
@@ -996,3 +1014,37 @@ struct msgb *ms_nacc_create_rlcmac_msg(struct GprsMs *ms, struct gprs_rlcmac_tbf
return NULL;
return data_ctx.msg;
}
+
+static void ms_start_llc_timer(struct GprsMs *ms)
+{
+ if (the_pcu->vty.llc_idle_ack_csec > 0) {
+ struct timespec tv;
+ csecs_to_timespec(the_pcu->vty.llc_idle_ack_csec, &tv);
+ osmo_timer_schedule(&ms->llc_timer, tv.tv_sec, tv.tv_nsec / 1000);
+ }
+}
+
+int ms_append_llc_dl_data(struct GprsMs *ms, uint16_t pdu_delay_csec, const uint8_t *data, uint16_t len)
+{
+ struct timespec expire_time;
+ struct gprs_rlcmac_dl_tbf *dl_tbf;
+
+ LOGPMS(ms, DTBFDL, LOGL_DEBUG, "appending %u bytes to DL LLC queue\n", len);
+
+ struct msgb *llc_msg = msgb_alloc(len, "llc_pdu_queue");
+ if (!llc_msg)
+ return -ENOMEM;
+
+ llc_queue_calc_pdu_lifetime(ms->bts, pdu_delay_csec, &expire_time);
+ memcpy(msgb_put(llc_msg, len), data, len);
+ llc_queue_enqueue(ms_llc_queue(ms), llc_msg, &expire_time);
+ ms_start_llc_timer(ms);
+
+ dl_tbf = ms_dl_tbf(ms);
+ if (dl_tbf && tbf_state((const struct gprs_rlcmac_tbf *)dl_tbf) == TBF_ST_WAIT_RELEASE) {
+ LOGPTBFDL((const struct gprs_rlcmac_tbf *)dl_tbf, LOGL_DEBUG, "in WAIT RELEASE state (T3193), so reuse TBF\n");
+ tbf_establish_dl_tbf_on_pacch((struct gprs_rlcmac_tbf *)dl_tbf);
+ }
+
+ return 0;
+}
diff --git a/src/gprs_ms.h b/src/gprs_ms.h
index cc92e2ab..703e84bc 100644
--- a/src/gprs_ms.h
+++ b/src/gprs_ms.h
@@ -79,6 +79,7 @@ struct GprsMs {
enum CodingScheme current_cs_dl;
struct gprs_llc_queue llc_queue;
+ struct osmo_timer_list llc_timer;
bool is_idle;
int ref;
@@ -143,6 +144,8 @@ int ms_nacc_start(struct GprsMs *ms, Packet_Cell_Change_Notification_t *notif);
bool ms_nacc_rts(const struct GprsMs *ms);
struct msgb *ms_nacc_create_rlcmac_msg(struct GprsMs *ms, struct gprs_rlcmac_tbf *tbf, uint32_t fn, uint8_t ts);
+int ms_append_llc_dl_data(struct GprsMs *ms, uint16_t pdu_delay_csec, const uint8_t *data, uint16_t len);
+
static inline bool ms_is_idle(const struct GprsMs *ms)
{
return !ms->ul_tbf && !ms->dl_tbf && !ms->ref && llist_empty(&ms->old_tbfs);
diff --git a/src/tbf.cpp b/src/tbf.cpp
index cb5d9f30..5597ba49 100644
--- a/src/tbf.cpp
+++ b/src/tbf.cpp
@@ -950,3 +950,8 @@ const char* tbf_rlcmac_diag(const struct gprs_rlcmac_tbf *tbf)
return buf;
}
+
+int tbf_establish_dl_tbf_on_pacch(struct gprs_rlcmac_tbf *tbf)
+{
+ return tbf->establish_dl_tbf_on_pacch();
+}
diff --git a/src/tbf.h b/src/tbf.h
index 31bbe5fa..b34476e7 100644
--- a/src/tbf.h
+++ b/src/tbf.h
@@ -148,6 +148,7 @@ const char* tbf_rlcmac_diag(const struct gprs_rlcmac_tbf *tbf);
bool tbf_is_control_ts(const struct gprs_rlcmac_tbf *tbf, uint8_t ts);
bool tbf_can_upgrade_to_multislot(const struct gprs_rlcmac_tbf *tbf);
int tbf_update(struct gprs_rlcmac_tbf *tbf);
+int tbf_establish_dl_tbf_on_pacch(struct gprs_rlcmac_tbf *tbf);
#ifdef __cplusplus
}
#endif
diff --git a/src/tbf_dl.cpp b/src/tbf_dl.cpp
index 67ac573e..6d02c8e6 100644
--- a/src/tbf_dl.cpp
+++ b/src/tbf_dl.cpp
@@ -90,18 +90,6 @@ static const struct rate_ctr_group_desc tbf_dl_egprs_ctrg_desc = {
tbf_dl_egprs_ctr_description,
};
-static void llc_timer_cb(void *_tbf)
-{
- struct gprs_rlcmac_dl_tbf *tbf = (struct gprs_rlcmac_dl_tbf *)_tbf;
-
- if (tbf->state_is_not(TBF_ST_FLOW))
- return;
-
- LOGPTBFDL(tbf, LOGL_DEBUG, "LLC receive timeout, requesting DL ACK\n");
-
- tbf->request_dl_ack();
-}
-
gprs_rlcmac_dl_tbf::BandWidth::BandWidth() :
dl_bw_octets(0),
dl_throughput(0),
@@ -175,7 +163,6 @@ struct gprs_rlcmac_dl_tbf *tbf_alloc_dl_tbf(struct gprs_rlcmac_bts *bts, GprsMs
gprs_rlcmac_dl_tbf::~gprs_rlcmac_dl_tbf()
{
- osmo_timer_del(&m_llc_timer);
if (is_egprs_enabled()) {
rate_ctr_group_free(m_dl_egprs_ctrs);
} else {
@@ -193,41 +180,6 @@ gprs_rlcmac_dl_tbf::gprs_rlcmac_dl_tbf(struct gprs_rlcmac_bts *bts_, GprsMs *ms)
m_dl_gprs_ctrs(NULL),
m_dl_egprs_ctrs(NULL)
{
- memset(&m_llc_timer, 0, sizeof(m_llc_timer));
- osmo_timer_setup(&m_llc_timer, llc_timer_cb, this);
-}
-
-void gprs_rlcmac_dl_tbf::start_llc_timer()
-{
- if (the_pcu->vty.llc_idle_ack_csec > 0) {
- struct timespec tv;
- csecs_to_timespec(the_pcu->vty.llc_idle_ack_csec, &tv);
- osmo_timer_schedule(&m_llc_timer, tv.tv_sec, tv.tv_nsec / 1000);
- }
-}
-
-int gprs_rlcmac_dl_tbf::append_data(uint16_t pdu_delay_csec,
- const uint8_t *data, uint16_t len)
-{
- struct timespec expire_time;
-
- LOGPTBFDL(this, LOGL_DEBUG, "appending %u bytes\n", len);
-
- struct msgb *llc_msg = msgb_alloc(len, "llc_pdu_queue");
- if (!llc_msg)
- return -ENOMEM;
-
- llc_queue_calc_pdu_lifetime(bts, pdu_delay_csec, &expire_time);
- memcpy(msgb_put(llc_msg, len), data, len);
- llc_queue_enqueue(llc_queue(), llc_msg, &expire_time);
- start_llc_timer();
-
- if (state_is(TBF_ST_WAIT_RELEASE)) {
- LOGPTBFDL(this, LOGL_DEBUG, "in WAIT RELEASE state (T3193), so reuse TBF\n");
- establish_dl_tbf_on_pacch();
- }
-
- return 0;
}
static int tbf_new_dl_assignment(struct gprs_rlcmac_bts *bts, GprsMs *ms,
@@ -331,16 +283,17 @@ int dl_tbf_handle(struct gprs_rlcmac_bts *bts,
ms_set_egprs_ms_class(ms, egprs_ms_class);
}
+ rc = ms_append_llc_dl_data(ms, delay_csec, data, len);
+ if (rc < 0)
+ return rc;
+
dl_tbf = ms_dl_tbf(ms);
if (!dl_tbf) {
rc = tbf_new_dl_assignment(bts, ms, &dl_tbf);
if (rc < 0)
return rc;
}
-
- rc = dl_tbf->append_data(delay_csec, data, len);
-
- return rc;
+ return 0;
}
bool gprs_rlcmac_dl_tbf::restart_bsn_cycle()
@@ -1115,6 +1068,10 @@ void gprs_rlcmac_dl_tbf::request_dl_ack()
m_dl_ack_requested = true;
}
+void tbf_dl_request_dl_ack(struct gprs_rlcmac_dl_tbf *dl_tbf) {
+ dl_tbf->request_dl_ack();
+}
+
/* Does this DL TBF require to poll the MS for DL ACK/NACK? */
bool gprs_rlcmac_dl_tbf::need_poll_for_dl_ack_nack() const
{
diff --git a/src/tbf_dl.h b/src/tbf_dl.h
index 0f531eca..59206727 100644
--- a/src/tbf_dl.h
+++ b/src/tbf_dl.h
@@ -39,9 +39,6 @@ struct gprs_rlcmac_dl_tbf : public gprs_rlcmac_tbf {
~gprs_rlcmac_dl_tbf();
gprs_rlc_window *window();
- int append_data(uint16_t pdu_delay_csec,
- const uint8_t *data, uint16_t len);
-
int rcvd_dl_ack(bool final_ack, unsigned first_bsn, struct bitvec *rbb);
struct msgb *create_dl_acked_block(uint32_t fn, uint8_t ts, enum mcs_kind req_mcs_kind = EGPRS);
void trigger_ass(struct gprs_rlcmac_tbf *old_tbf);
@@ -100,7 +97,6 @@ protected:
int rcvd_dl_final_ack();
bool dl_window_stalled() const;
void reuse_tbf();
- void start_llc_timer();
int analyse_errors(char *show_rbb, uint8_t ssn, ana_result *res);
void schedule_next_frame();
@@ -109,8 +105,6 @@ protected:
unsigned int get_egprs_dl_spb_status(int bsn);
enum egprs_rlcmac_dl_spb get_egprs_dl_spb(int bsn);
- struct osmo_timer_list m_llc_timer;
-
/* Please note that all variables below will be reset when changing
* from WAIT RELEASE back to FLOW state (re-use of TBF).
* All states that need reset must be in this struct, so this is why
@@ -145,6 +139,7 @@ int dl_tbf_handle(struct gprs_rlcmac_bts *bts,
const uint8_t *data, const uint16_t len);
void tbf_dl_trigger_ass(struct gprs_rlcmac_dl_tbf *tbf, struct gprs_rlcmac_tbf *old_tbf);
+void tbf_dl_request_dl_ack(struct gprs_rlcmac_dl_tbf *tbf);
#define LOGPTBFDL(tbf, level, fmt, args...) LOGP(DTBFDL, level, "%s " fmt, tbf_name(tbf), ## args)
#ifdef __cplusplus