forked from cellular-infrastructure/osmo-pcu
tbf: Move the llc handling into the tbf (from the bts)
This will be moved to a LLC class in the future but after this we can make the sns/ws private now and have little to update outside the tbf.
This commit is contained in:
parent
bc1626e5de
commit
77e05971b4
187
src/bts.cpp
187
src/bts.cpp
|
@ -511,9 +511,6 @@ void BTS::snd_dl_ass(gprs_rlcmac_tbf *tbf, uint8_t poll, const char *imsi)
|
|||
* PDCH code below. TODO: move to a separate file
|
||||
*/
|
||||
|
||||
/* After receiving these frames, we send ack/nack. */
|
||||
#define SEND_ACK_AFTER_FRAMES 20
|
||||
|
||||
void gprs_rlcmac_pdch::enable()
|
||||
{
|
||||
/* TODO: Check if there are still allocated resources.. */
|
||||
|
@ -650,8 +647,6 @@ int gprs_rlcmac_pdch::rcv_data_block_acknowledged(uint8_t *data, uint8_t len, in
|
|||
{
|
||||
struct gprs_rlcmac_tbf *tbf;
|
||||
struct rlc_ul_header *rh = (struct rlc_ul_header *)data;
|
||||
uint16_t mod_sns, mod_sns_half, offset_v_q, offset_v_r, index;
|
||||
int rc;
|
||||
|
||||
switch (len) {
|
||||
case 54:
|
||||
|
@ -682,188 +677,8 @@ int gprs_rlcmac_pdch::rcv_data_block_acknowledged(uint8_t *data, uint8_t len, in
|
|||
rh->tfi);
|
||||
return 0;
|
||||
}
|
||||
tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_UL_DATA);
|
||||
|
||||
LOGP(DRLCMACUL, LOGL_DEBUG, "UL DATA TFI=%d received (V(Q)=%d .. "
|
||||
"V(R)=%d)\n", rh->tfi, tbf->dir.ul.v_q, tbf->dir.ul.v_r);
|
||||
|
||||
/* process RSSI */
|
||||
gprs_rlcmac_rssi(tbf, rssi);
|
||||
|
||||
/* get TLLI */
|
||||
if (!tbf->is_tlli_valid()) {
|
||||
struct gprs_rlcmac_tbf *dl_tbf, *ul_tbf;
|
||||
uint32_t tlli;
|
||||
|
||||
/* no TLLI yet */
|
||||
if (!rh->ti) {
|
||||
LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA TFI=%d without "
|
||||
"TLLI, but no TLLI received yet\n", rh->tfi);
|
||||
return 0;
|
||||
}
|
||||
rc = Decoding::tlli_from_ul_data(data, len, &tlli);
|
||||
if (rc) {
|
||||
bts()->decode_error();
|
||||
LOGP(DRLCMACUL, LOGL_NOTICE, "Failed to decode TLLI "
|
||||
"of UL DATA TFI=%d.\n", rh->tfi);
|
||||
return 0;
|
||||
}
|
||||
tbf->update_tlli(tlli);
|
||||
LOGP(DRLCMACUL, LOGL_INFO, "Decoded premier TLLI=0x%08x of "
|
||||
"UL DATA TFI=%d.\n", tbf->tlli(), rh->tfi);
|
||||
if ((dl_tbf = bts()->tbf_by_tlli(tbf->tlli(), GPRS_RLCMAC_DL_TBF))) {
|
||||
LOGP(DRLCMACUL, LOGL_NOTICE, "Got RACH from "
|
||||
"TLLI=0x%08x while %s still exists. "
|
||||
"Killing pending DL TBF\n", tbf->tlli(),
|
||||
tbf_name(dl_tbf));
|
||||
tbf_free(dl_tbf);
|
||||
}
|
||||
/* tbf_by_tlli will not find your TLLI, because it is not
|
||||
* yet marked valid */
|
||||
if ((ul_tbf = bts()->tbf_by_tlli(tbf->tlli(), GPRS_RLCMAC_UL_TBF))) {
|
||||
LOGP(DRLCMACUL, LOGL_NOTICE, "Got RACH from "
|
||||
"TLLI=0x%08x while %s still exists. "
|
||||
"Killing pending UL TBF\n", tbf->tlli(),
|
||||
tbf_name(ul_tbf));
|
||||
tbf_free(ul_tbf);
|
||||
}
|
||||
/* mark TLLI valid now */
|
||||
tbf->tlli_mark_valid();
|
||||
/* store current timing advance */
|
||||
bts()->timing_advance()->remember(tbf->tlli(), tbf->ta);
|
||||
/* already have TLLI, but we stille get another one */
|
||||
} else if (rh->ti) {
|
||||
uint32_t tlli;
|
||||
rc = Decoding::tlli_from_ul_data(data, len, &tlli);
|
||||
if (rc) {
|
||||
LOGP(DRLCMACUL, LOGL_NOTICE, "Failed to decode TLLI "
|
||||
"of UL DATA TFI=%d.\n", rh->tfi);
|
||||
return 0;
|
||||
}
|
||||
if (tlli != tbf->tlli()) {
|
||||
LOGP(DRLCMACUL, LOGL_NOTICE, "TLLI mismatch on UL "
|
||||
"DATA TFI=%d. (Ignoring due to contention "
|
||||
"resolution)\n", rh->tfi);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
mod_sns = tbf->sns - 1;
|
||||
mod_sns_half = (tbf->sns >> 1) - 1;
|
||||
|
||||
/* restart T3169 */
|
||||
tbf_timer_start(tbf, 3169, bts_data()->t3169, 0);
|
||||
|
||||
/* Increment RX-counter */
|
||||
tbf->dir.ul.rx_counter++;
|
||||
|
||||
/* current block relative to lowest unreceived block */
|
||||
offset_v_q = (rh->bsn - tbf->dir.ul.v_q) & mod_sns;
|
||||
/* If out of window (may happen if blocks below V(Q) are received
|
||||
* again. */
|
||||
if (offset_v_q >= tbf->ws) {
|
||||
LOGP(DRLCMACUL, LOGL_DEBUG, "- BSN %d out of window "
|
||||
"%d..%d (it's normal)\n", rh->bsn, tbf->dir.ul.v_q,
|
||||
(tbf->dir.ul.v_q + tbf->ws - 1) & mod_sns);
|
||||
return 0;
|
||||
}
|
||||
/* Write block to buffer and set receive state array. */
|
||||
index = rh->bsn & mod_sns_half; /* memory index of block */
|
||||
memcpy(tbf->rlc_block[index], data, len); /* Copy block. */
|
||||
tbf->rlc_block_len[index] = len;
|
||||
tbf->dir.ul.v_n[index] = 'R'; /* Mark received block. */
|
||||
LOGP(DRLCMACUL, LOGL_DEBUG, "- BSN %d storing in window (%d..%d)\n",
|
||||
rh->bsn, tbf->dir.ul.v_q,
|
||||
(tbf->dir.ul.v_q + tbf->ws - 1) & mod_sns);
|
||||
/* Raise V(R) to highest received sequence number not received. */
|
||||
offset_v_r = (rh->bsn + 1 - tbf->dir.ul.v_r) & mod_sns;
|
||||
if (offset_v_r < (tbf->sns >> 1)) { /* Positive offset, so raise. */
|
||||
while (offset_v_r--) {
|
||||
if (offset_v_r) /* all except the received block */
|
||||
tbf->dir.ul.v_n[tbf->dir.ul.v_r & mod_sns_half]
|
||||
= 'N'; /* Mark block as not received */
|
||||
tbf->dir.ul.v_r = (tbf->dir.ul.v_r + 1) & mod_sns;
|
||||
/* Inc V(R). */
|
||||
}
|
||||
LOGP(DRLCMACUL, LOGL_DEBUG, "- Raising V(R) to %d\n",
|
||||
tbf->dir.ul.v_r);
|
||||
}
|
||||
|
||||
#warning "Move to TBF and remove the index side effect.."
|
||||
/* Raise V(Q) if possible, and retrieve LLC frames from blocks.
|
||||
* This is looped until there is a gap (non received block) or
|
||||
* the window is empty.*/
|
||||
while (tbf->dir.ul.v_q != tbf->dir.ul.v_r && tbf->dir.ul.v_n[
|
||||
(index = tbf->dir.ul.v_q & mod_sns_half)] == 'R') {
|
||||
LOGP(DRLCMACUL, LOGL_DEBUG, "- Taking block %d out, raising "
|
||||
"V(Q) to %d\n", tbf->dir.ul.v_q,
|
||||
(tbf->dir.ul.v_q + 1) & mod_sns);
|
||||
/* get LLC data from block */
|
||||
tbf->assemble_forward_llc(tbf->rlc_block[index], tbf->rlc_block_len[index]);
|
||||
/* raise V(Q), because block already received */
|
||||
tbf->dir.ul.v_q = (tbf->dir.ul.v_q + 1) & mod_sns;
|
||||
}
|
||||
|
||||
/* Check CV of last frame in buffer */
|
||||
if (tbf->state_is(GPRS_RLCMAC_FLOW) /* still in flow state */
|
||||
&& tbf->dir.ul.v_q == tbf->dir.ul.v_r) { /* if complete */
|
||||
struct rlc_ul_header *last_rh = (struct rlc_ul_header *)
|
||||
tbf->rlc_block[(tbf->dir.ul.v_r - 1) & mod_sns_half];
|
||||
LOGP(DRLCMACUL, LOGL_DEBUG, "- No gaps in received block, "
|
||||
"last block: BSN=%d CV=%d\n", last_rh->bsn,
|
||||
last_rh->cv);
|
||||
if (last_rh->cv == 0) {
|
||||
LOGP(DRLCMACUL, LOGL_DEBUG, "- Finished with UL "
|
||||
"TBF\n");
|
||||
tbf_new_state(tbf, GPRS_RLCMAC_FINISHED);
|
||||
/* Reset N3103 counter. */
|
||||
tbf->dir.ul.n3103 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* If TLLI is included or if we received half of the window, we send
|
||||
* an ack/nack */
|
||||
if (rh->si || rh->ti || tbf->state_is(GPRS_RLCMAC_FINISHED)
|
||||
|| (tbf->dir.ul.rx_counter % SEND_ACK_AFTER_FRAMES) == 0) {
|
||||
if (rh->si) {
|
||||
LOGP(DRLCMACUL, LOGL_NOTICE, "- Scheduling Ack/Nack, "
|
||||
"because MS is stalled.\n");
|
||||
}
|
||||
if (rh->ti) {
|
||||
LOGP(DRLCMACUL, LOGL_DEBUG, "- Scheduling Ack/Nack, "
|
||||
"because TLLI is included.\n");
|
||||
}
|
||||
if (tbf->state_is(GPRS_RLCMAC_FINISHED)) {
|
||||
LOGP(DRLCMACUL, LOGL_DEBUG, "- Scheduling Ack/Nack, "
|
||||
"because last block has CV==0.\n");
|
||||
}
|
||||
if ((tbf->dir.ul.rx_counter % SEND_ACK_AFTER_FRAMES) == 0) {
|
||||
LOGP(DRLCMACUL, LOGL_DEBUG, "- Scheduling Ack/Nack, "
|
||||
"because %d frames received.\n",
|
||||
SEND_ACK_AFTER_FRAMES);
|
||||
}
|
||||
if (tbf->ul_ack_state == GPRS_RLCMAC_UL_ACK_NONE) {
|
||||
#ifdef DEBUG_DIAGRAM
|
||||
if (rh->si)
|
||||
debug_diagram(bts->bts, tbf->diag, "sched UL-ACK stall");
|
||||
if (rh->ti)
|
||||
debug_diagram(bts->bts, tbf->diag, "sched UL-ACK TLLI");
|
||||
if (tbf->state_is(GPRS_RLCMAC_FINISHED))
|
||||
debug_diagram(bts->bts, tbf->diag, "sched UL-ACK CV==0");
|
||||
if ((tbf->dir.ul.rx_counter % SEND_ACK_AFTER_FRAMES) == 0)
|
||||
debug_diagram(bts->bts, tbf->diag, "sched UL-ACK n=%d",
|
||||
tbf->dir.ul.rx_counter);
|
||||
#endif
|
||||
/* trigger sending at next RTS */
|
||||
tbf->ul_ack_state = GPRS_RLCMAC_UL_ACK_SEND_ACK;
|
||||
} else {
|
||||
/* already triggered */
|
||||
LOGP(DRLCMACUL, LOGL_DEBUG, "- Sending Ack/Nack is "
|
||||
"already triggered, don't schedule!\n");
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return tbf->rcv_data_block_acknowledged(data, len, rssi);
|
||||
}
|
||||
|
||||
void gprs_rlcmac_pdch::rcv_control_ack(Packet_Control_Acknowledgement_t *packet, uint32_t fn)
|
||||
|
|
194
src/tbf.cpp
194
src/tbf.cpp
|
@ -26,6 +26,7 @@
|
|||
#include <gprs_rlcmac.h>
|
||||
#include <gprs_debug.h>
|
||||
#include <gprs_bssgp_pcu.h>
|
||||
#include <decoding.h>
|
||||
|
||||
extern "C" {
|
||||
#include <osmocom/core/msgb.h>
|
||||
|
@ -37,6 +38,9 @@ extern "C" {
|
|||
|
||||
/* After sending these frames, we poll for ack/nack. */
|
||||
#define POLL_ACK_AFTER_FRAMES 20
|
||||
/* After receiving these frames, we send ack/nack. */
|
||||
#define SEND_ACK_AFTER_FRAMES 20
|
||||
|
||||
|
||||
/* If acknowledgement to downlink assignment should be polled */
|
||||
#define POLLING_ASSIGNMENT_DL 1
|
||||
|
@ -1650,6 +1654,196 @@ void gprs_rlcmac_tbf::update_tlli(uint32_t tlli)
|
|||
m_tlli = tlli;
|
||||
}
|
||||
|
||||
int gprs_rlcmac_tbf::rcv_data_block_acknowledged(const uint8_t *data, size_t len, int8_t rssi)
|
||||
{
|
||||
uint16_t mod_sns, mod_sns_half, offset_v_q, offset_v_r, index;
|
||||
struct rlc_ul_header *rh = (struct rlc_ul_header *)data;
|
||||
int rc;
|
||||
|
||||
this->state_flags |= (1 << GPRS_RLCMAC_FLAG_UL_DATA);
|
||||
|
||||
LOGP(DRLCMACUL, LOGL_DEBUG, "UL DATA TFI=%d received (V(Q)=%d .. "
|
||||
"V(R)=%d)\n", rh->tfi, this->dir.ul.v_q, this->dir.ul.v_r);
|
||||
|
||||
/* process RSSI */
|
||||
gprs_rlcmac_rssi(this, rssi);
|
||||
|
||||
/* get TLLI */
|
||||
if (!this->is_tlli_valid()) {
|
||||
struct gprs_rlcmac_tbf *dl_tbf, *ul_tbf;
|
||||
uint32_t tlli;
|
||||
|
||||
/* no TLLI yet */
|
||||
if (!rh->ti) {
|
||||
LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA TFI=%d without "
|
||||
"TLLI, but no TLLI received yet\n", rh->tfi);
|
||||
return 0;
|
||||
}
|
||||
rc = Decoding::tlli_from_ul_data(data, len, &tlli);
|
||||
if (rc) {
|
||||
bts->decode_error();
|
||||
LOGP(DRLCMACUL, LOGL_NOTICE, "Failed to decode TLLI "
|
||||
"of UL DATA TFI=%d.\n", rh->tfi);
|
||||
return 0;
|
||||
}
|
||||
this->update_tlli(tlli);
|
||||
LOGP(DRLCMACUL, LOGL_INFO, "Decoded premier TLLI=0x%08x of "
|
||||
"UL DATA TFI=%d.\n", this->tlli(), rh->tfi);
|
||||
if ((dl_tbf = bts->tbf_by_tlli(this->tlli(), GPRS_RLCMAC_DL_TBF))) {
|
||||
LOGP(DRLCMACUL, LOGL_NOTICE, "Got RACH from "
|
||||
"TLLI=0x%08x while %s still exists. "
|
||||
"Killing pending DL TBF\n", this->tlli(),
|
||||
tbf_name(dl_tbf));
|
||||
tbf_free(dl_tbf);
|
||||
}
|
||||
/* tbf_by_tlli will not find your TLLI, because it is not
|
||||
* yet marked valid */
|
||||
if ((ul_tbf = bts->tbf_by_tlli(this->tlli(), GPRS_RLCMAC_UL_TBF))) {
|
||||
LOGP(DRLCMACUL, LOGL_NOTICE, "Got RACH from "
|
||||
"TLLI=0x%08x while %s still exists. "
|
||||
"Killing pending UL TBF\n", this->tlli(),
|
||||
tbf_name(ul_tbf));
|
||||
tbf_free(ul_tbf);
|
||||
}
|
||||
/* mark TLLI valid now */
|
||||
this->tlli_mark_valid();
|
||||
/* store current timing advance */
|
||||
bts->timing_advance()->remember(this->tlli(), this->ta);
|
||||
/* already have TLLI, but we stille get another one */
|
||||
} else if (rh->ti) {
|
||||
uint32_t tlli;
|
||||
rc = Decoding::tlli_from_ul_data(data, len, &tlli);
|
||||
if (rc) {
|
||||
LOGP(DRLCMACUL, LOGL_NOTICE, "Failed to decode TLLI "
|
||||
"of UL DATA TFI=%d.\n", rh->tfi);
|
||||
return 0;
|
||||
}
|
||||
if (tlli != this->tlli()) {
|
||||
LOGP(DRLCMACUL, LOGL_NOTICE, "TLLI mismatch on UL "
|
||||
"DATA TFI=%d. (Ignoring due to contention "
|
||||
"resolution)\n", rh->tfi);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
mod_sns = this->sns - 1;
|
||||
mod_sns_half = (this->sns >> 1) - 1;
|
||||
|
||||
/* restart T3169 */
|
||||
tbf_timer_start(this, 3169, bts_data()->t3169, 0);
|
||||
|
||||
/* Increment RX-counter */
|
||||
this->dir.ul.rx_counter++;
|
||||
|
||||
/* current block relative to lowest unreceived block */
|
||||
offset_v_q = (rh->bsn - this->dir.ul.v_q) & mod_sns;
|
||||
/* If out of window (may happen if blocks below V(Q) are received
|
||||
* again. */
|
||||
if (offset_v_q >= this->ws) {
|
||||
LOGP(DRLCMACUL, LOGL_DEBUG, "- BSN %d out of window "
|
||||
"%d..%d (it's normal)\n", rh->bsn, this->dir.ul.v_q,
|
||||
(this->dir.ul.v_q + this->ws - 1) & mod_sns);
|
||||
return 0;
|
||||
}
|
||||
/* Write block to buffer and set receive state array. */
|
||||
index = rh->bsn & mod_sns_half; /* memory index of block */
|
||||
memcpy(this->rlc_block[index], data, len); /* Copy block. */
|
||||
this->rlc_block_len[index] = len;
|
||||
this->dir.ul.v_n[index] = 'R'; /* Mark received block. */
|
||||
LOGP(DRLCMACUL, LOGL_DEBUG, "- BSN %d storing in window (%d..%d)\n",
|
||||
rh->bsn, this->dir.ul.v_q,
|
||||
(this->dir.ul.v_q + this->ws - 1) & mod_sns);
|
||||
/* Raise V(R) to highest received sequence number not received. */
|
||||
offset_v_r = (rh->bsn + 1 - this->dir.ul.v_r) & mod_sns;
|
||||
if (offset_v_r < (this->sns >> 1)) { /* Positive offset, so raise. */
|
||||
while (offset_v_r--) {
|
||||
if (offset_v_r) /* all except the received block */
|
||||
this->dir.ul.v_n[this->dir.ul.v_r & mod_sns_half]
|
||||
= 'N'; /* Mark block as not received */
|
||||
this->dir.ul.v_r = (this->dir.ul.v_r + 1) & mod_sns;
|
||||
/* Inc V(R). */
|
||||
}
|
||||
LOGP(DRLCMACUL, LOGL_DEBUG, "- Raising V(R) to %d\n",
|
||||
this->dir.ul.v_r);
|
||||
}
|
||||
|
||||
#warning "Move to TBF and remove the index side effect.."
|
||||
/* Raise V(Q) if possible, and retrieve LLC frames from blocks.
|
||||
* This is looped until there is a gap (non received block) or
|
||||
* the window is empty.*/
|
||||
while (this->dir.ul.v_q != this->dir.ul.v_r && this->dir.ul.v_n[
|
||||
(index = this->dir.ul.v_q & mod_sns_half)] == 'R') {
|
||||
LOGP(DRLCMACUL, LOGL_DEBUG, "- Taking block %d out, raising "
|
||||
"V(Q) to %d\n", this->dir.ul.v_q,
|
||||
(this->dir.ul.v_q + 1) & mod_sns);
|
||||
/* get LLC data from block */
|
||||
this->assemble_forward_llc(this->rlc_block[index], this->rlc_block_len[index]);
|
||||
/* raise V(Q), because block already received */
|
||||
this->dir.ul.v_q = (this->dir.ul.v_q + 1) & mod_sns;
|
||||
}
|
||||
|
||||
/* Check CV of last frame in buffer */
|
||||
if (this->state_is(GPRS_RLCMAC_FLOW) /* still in flow state */
|
||||
&& this->dir.ul.v_q == this->dir.ul.v_r) { /* if complete */
|
||||
struct rlc_ul_header *last_rh = (struct rlc_ul_header *)
|
||||
this->rlc_block[(this->dir.ul.v_r - 1) & mod_sns_half];
|
||||
LOGP(DRLCMACUL, LOGL_DEBUG, "- No gaps in received block, "
|
||||
"last block: BSN=%d CV=%d\n", last_rh->bsn,
|
||||
last_rh->cv);
|
||||
if (last_rh->cv == 0) {
|
||||
LOGP(DRLCMACUL, LOGL_DEBUG, "- Finished with UL "
|
||||
"TBF\n");
|
||||
tbf_new_state(this, GPRS_RLCMAC_FINISHED);
|
||||
/* Reset N3103 counter. */
|
||||
this->dir.ul.n3103 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* If TLLI is included or if we received half of the window, we send
|
||||
* an ack/nack */
|
||||
if (rh->si || rh->ti || this->state_is(GPRS_RLCMAC_FINISHED)
|
||||
|| (this->dir.ul.rx_counter % SEND_ACK_AFTER_FRAMES) == 0) {
|
||||
if (rh->si) {
|
||||
LOGP(DRLCMACUL, LOGL_NOTICE, "- Scheduling Ack/Nack, "
|
||||
"because MS is stalled.\n");
|
||||
}
|
||||
if (rh->ti) {
|
||||
LOGP(DRLCMACUL, LOGL_DEBUG, "- Scheduling Ack/Nack, "
|
||||
"because TLLI is included.\n");
|
||||
}
|
||||
if (this->state_is(GPRS_RLCMAC_FINISHED)) {
|
||||
LOGP(DRLCMACUL, LOGL_DEBUG, "- Scheduling Ack/Nack, "
|
||||
"because last block has CV==0.\n");
|
||||
}
|
||||
if ((this->dir.ul.rx_counter % SEND_ACK_AFTER_FRAMES) == 0) {
|
||||
LOGP(DRLCMACUL, LOGL_DEBUG, "- Scheduling Ack/Nack, "
|
||||
"because %d frames received.\n",
|
||||
SEND_ACK_AFTER_FRAMES);
|
||||
}
|
||||
if (this->ul_ack_state == GPRS_RLCMAC_UL_ACK_NONE) {
|
||||
#ifdef DEBUG_DIAGRAM
|
||||
if (rh->si)
|
||||
debug_diagram(bts->bts, this->diag, "sched UL-ACK stall");
|
||||
if (rh->ti)
|
||||
debug_diagram(bts->bts, this->diag, "sched UL-ACK TLLI");
|
||||
if (this->state_is(GPRS_RLCMAC_FINISHED))
|
||||
debug_diagram(bts->bts, this->diag, "sched UL-ACK CV==0");
|
||||
if ((this->dir.ul.rx_counter % SEND_ACK_AFTER_FRAMES) == 0)
|
||||
debug_diagram(bts->bts, this->diag, "sched UL-ACK n=%d",
|
||||
this->dir.ul.rx_counter);
|
||||
#endif
|
||||
/* trigger sending at next RTS */
|
||||
this->ul_ack_state = GPRS_RLCMAC_UL_ACK_SEND_ACK;
|
||||
} else {
|
||||
/* already triggered */
|
||||
LOGP(DRLCMACUL, LOGL_DEBUG, "- Sending Ack/Nack is "
|
||||
"already triggered, don't schedule!\n");
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *tbf_name(gprs_rlcmac_tbf *tbf)
|
||||
{
|
||||
static char buf[40];
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <stdint.h>
|
||||
|
||||
struct bssgp_bvc_ctx;
|
||||
struct rlc_ul_header;
|
||||
|
||||
/*
|
||||
* TBF instance
|
||||
|
@ -105,6 +106,9 @@ struct gprs_rlcmac_tbf {
|
|||
struct msgb *create_ul_ack(uint32_t fn);
|
||||
int snd_dl_ack(uint8_t final, uint8_t ssn, uint8_t *rbb);
|
||||
|
||||
/* blocks were acked */
|
||||
int rcv_data_block_acknowledged(const uint8_t *data, size_t len, int8_t rssi);
|
||||
|
||||
int rlcmac_diag();
|
||||
|
||||
int update();
|
||||
|
|
Loading…
Reference in New Issue