diff options
-rw-r--r-- | src/gprs_bssgp_pcu.cpp | 57 | ||||
-rw-r--r-- | src/gprs_bssgp_pcu.h | 5 | ||||
-rw-r--r-- | src/gprs_rlcmac_sched.cpp | 3 | ||||
-rw-r--r-- | src/tbf.h | 9 | ||||
-rw-r--r-- | src/tbf_dl.cpp | 36 | ||||
-rw-r--r-- | tests/tbf/TbfTest.err | 2 |
6 files changed, 106 insertions, 6 deletions
diff --git a/src/gprs_bssgp_pcu.cpp b/src/gprs_bssgp_pcu.cpp index 7f50e17d..cce184d5 100644 --- a/src/gprs_bssgp_pcu.cpp +++ b/src/gprs_bssgp_pcu.cpp @@ -591,6 +591,32 @@ static uint32_t get_and_reset_avg_queue_delay(void) return avg_delay_ms; } +static int get_and_reset_measured_leak_rate(int *usage_by_1000, unsigned num_pdch) +{ + int rate; /* byte per second */ + + if (the_pcu.queue_frames_sent == 0) + return -1; + + if (the_pcu.queue_frames_recv == 0) + return -1; + + *usage_by_1000 = the_pcu.queue_frames_recv * 1000 / + the_pcu.queue_frames_sent; + + /* 20ms/num_pdch is the average RLC block duration, so the rate is + * calculated as: + * rate = bytes_recv / (block_dur * block_count) */ + rate = the_pcu.queue_bytes_recv * 1000 * num_pdch / + (20 * the_pcu.queue_frames_recv); + + the_pcu.queue_frames_sent = 0; + the_pcu.queue_bytes_recv = 0; + the_pcu.queue_frames_recv = 0; + + return rate; +} + int gprs_bssgp_tx_fc_bvc(void) { struct gprs_rlcmac_bts *bts; @@ -630,6 +656,26 @@ int gprs_bssgp_tx_fc_bvc(void) ms_leak_rate = bts->fc_ms_leak_rate; if (leak_rate == 0) { + int meas_rate; + int usage; /* in 0..1000 */ + + if (num_pdch < 0) + num_pdch = count_pdch(bts); + + meas_rate = get_and_reset_measured_leak_rate(&usage, num_pdch); + if (meas_rate > 0) { + leak_rate = gprs_bssgp_max_leak_rate(max_cs_dl, num_pdch); + leak_rate = + (meas_rate * usage + leak_rate * (1000 - usage)) / + 1000; + LOGP(DBSSGP, LOGL_DEBUG, + "Estimated BVC leak rate = %d " + "(measured %d, usage %d%%)\n", + leak_rate, meas_rate, usage/10); + } + } + + if (leak_rate == 0) { if (num_pdch < 0) num_pdch = count_pdch(bts); @@ -853,6 +899,17 @@ struct bssgp_bvc_ctx *gprs_bssgp_pcu_current_bctx(void) return the_pcu.bctx; } +void gprs_bssgp_update_frames_sent() +{ + the_pcu.queue_frames_sent += 1; +} + +void gprs_bssgp_update_bytes_received(unsigned bytes_recv, unsigned frames_recv) +{ + the_pcu.queue_bytes_recv += bytes_recv; + the_pcu.queue_frames_recv += frames_recv; +} + void gprs_bssgp_update_queue_delay(const struct timeval *tv_recv, const struct timeval *tv_now) { diff --git a/src/gprs_bssgp_pcu.h b/src/gprs_bssgp_pcu.h index e0b83121..bb449034 100644 --- a/src/gprs_bssgp_pcu.h +++ b/src/gprs_bssgp_pcu.h @@ -62,6 +62,9 @@ struct gprs_bssgp_pcu { struct timeval queue_delay_sum; unsigned queue_delay_count; uint8_t fc_tag; + unsigned queue_frames_sent; + unsigned queue_bytes_recv; + unsigned queue_frames_recv; /** callbacks below */ @@ -86,5 +89,7 @@ struct bssgp_bvc_ctx *gprs_bssgp_pcu_current_bctx(void); void gprs_bssgp_update_queue_delay(const struct timeval *tv_recv, const struct timeval *tv_now); +void gprs_bssgp_update_frames_sent(); +void gprs_bssgp_update_bytes_received(unsigned bytes_recv, unsigned frames_recv); #endif // GPRS_BSSGP_PCU_H diff --git a/src/gprs_rlcmac_sched.cpp b/src/gprs_rlcmac_sched.cpp index dedea269..ac1991df 100644 --- a/src/gprs_rlcmac_sched.cpp +++ b/src/gprs_rlcmac_sched.cpp @@ -332,6 +332,9 @@ int gprs_rlcmac_rcv_rts_block(struct gprs_rlcmac_bts *bts, /* set USF */ msg->data[0] = (msg->data[0] & 0xf8) | usf; + /* Used to measure the leak rate, count all blocks */ + gprs_bssgp_update_frames_sent(); + /* send PDTCH/PACCH to L1 */ pcu_l1if_tx_pdtch(msg, trx, ts, arfcn, fn, block_nr); @@ -371,6 +371,13 @@ struct gprs_rlcmac_dl_tbf : public gprs_rlcmac_tbf { } m_bw; protected: + struct ana_result { + unsigned received_packets; + unsigned lost_packets; + unsigned received_bytes; + unsigned lost_bytes; + }; + struct msgb *create_new_bsn(const uint32_t fn, const uint8_t ts); struct msgb *create_dl_acked_block(const uint32_t fn, const uint8_t ts, const int index); @@ -379,7 +386,7 @@ protected: bool dl_window_stalled() const; void reuse_tbf(); void start_llc_timer(); - int analyse_errors(char *show_rbb, uint8_t ssn); + int analyse_errors(char *show_rbb, uint8_t ssn, ana_result *res); void schedule_next_frame(); struct osmo_timer_list m_llc_timer; diff --git a/src/tbf_dl.cpp b/src/tbf_dl.cpp index aabe8e3e..64fbef4e 100644 --- a/src/tbf_dl.cpp +++ b/src/tbf_dl.cpp @@ -712,7 +712,8 @@ static uint16_t bitnum_to_bsn(int bitnum, uint16_t ssn, uint16_t mod_sns) return (ssn - 1 - bitnum) & mod_sns; } -int gprs_rlcmac_dl_tbf::analyse_errors(char *show_rbb, uint8_t ssn) +int gprs_rlcmac_dl_tbf::analyse_errors(char *show_rbb, uint8_t ssn, + ana_result *res) { gprs_rlc_data *rlc_data; uint16_t lost = 0, received = 0, skipped = 0; @@ -720,9 +721,13 @@ int gprs_rlcmac_dl_tbf::analyse_errors(char *show_rbb, uint8_t ssn) memset(info, '.', sizeof(info)); info[64] = 0; uint16_t bsn = 0; + unsigned received_bytes = 0, lost_bytes = 0; + unsigned received_packets = 0, lost_packets = 0; /* SSN - 1 is in range V(A)..V(S)-1 */ for (int bitpos = 0; bitpos < m_window.ws(); bitpos++) { + bool is_received = show_rbb[m_window.ws() - 1 - bitpos] == 'R'; + bsn = bitnum_to_bsn(bitpos, ssn, m_window.mod_sns()); if (bsn == ((m_window.v_a() - 1) & m_window.mod_sns())) { @@ -736,6 +741,17 @@ int gprs_rlcmac_dl_tbf::analyse_errors(char *show_rbb, uint8_t ssn) continue; } + /* Get general statistics */ + if (is_received && !m_window.m_v_b.is_acked(bsn)) { + received_packets += 1; + received_bytes += rlc_data->len; + } else if (!is_received && !m_window.m_v_b.is_nacked(bsn)) { + lost_packets += 1; + lost_bytes += rlc_data->len; + } + + /* Get statistics for current CS */ + if (rlc_data->cs != current_cs()) { /* This block has already been encoded with a different * CS, so it doesn't help us to decide, whether the @@ -745,7 +761,7 @@ int gprs_rlcmac_dl_tbf::analyse_errors(char *show_rbb, uint8_t ssn) continue; } - if (show_rbb[m_window.ws() - 1 - bitpos] == 'R') { + if (is_received) { if (!m_window.m_v_b.is_acked(bsn)) { received += 1; info[bitpos] = 'R'; @@ -763,6 +779,11 @@ int gprs_rlcmac_dl_tbf::analyse_errors(char *show_rbb, uint8_t ssn) name(), m_window.v_a(), m_window.v_s(), lost, received, skipped, bsn, info); + res->received_packets = received_packets; + res->lost_packets = lost_packets; + res->received_bytes = received_bytes; + res->lost_bytes = lost_bytes; + if (lost + received <= 1) return -1; @@ -778,6 +799,7 @@ int gprs_rlcmac_dl_tbf::update_window(const uint8_t ssn, const uint8_t *rbb) char show_v_b[RLC_MAX_SNS + 1]; const uint16_t mod_sns = m_window.mod_sns(); int error_rate; + struct ana_result ana_res; Decoding::extract_rbb(rbb, show_rbb); /* show received array in debug (bit 64..1) */ @@ -800,10 +822,10 @@ int gprs_rlcmac_dl_tbf::update_window(const uint8_t ssn, const uint8_t *rbb) return 1; /* indicate to free TBF */ } - if (bts_data()->cs_adj_enabled && ms()) { - error_rate = analyse_errors(show_rbb, ssn); + error_rate = analyse_errors(show_rbb, ssn, &ana_res); + + if (bts_data()->cs_adj_enabled && ms()) ms()->update_error_rate(this, error_rate); - } m_window.update(bts, show_rbb, ssn, &lost, &received); @@ -811,6 +833,10 @@ int gprs_rlcmac_dl_tbf::update_window(const uint8_t ssn, const uint8_t *rbb) /* report lost and received packets */ gprs_rlcmac_received_lost(this, received, lost); + /* Used to measure the leak rate */ + gprs_bssgp_update_bytes_received(ana_res.received_bytes, + ana_res.received_packets + ana_res.lost_packets); + /* raise V(A), if possible */ m_window.raise(m_window.move_window()); diff --git a/tests/tbf/TbfTest.err b/tests/tbf/TbfTest.err index 70b5c570..2869ffd0 100644 --- a/tests/tbf/TbfTest.err +++ b/tests/tbf/TbfTest.err @@ -360,6 +360,7 @@ Polling is already sheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW), so Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=91 block=9 data=07 00 28 0a 41 c6 c7 43 c0 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) downlink acknowledge - ack: (BSN=85)"RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR"(BSN=20) R=ACK I=NACK +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) DL analysis, range=0:21, lost=0, recv=21, skipped=0, bsn=127, info='RRRRRRRRRRRRRRRRRRRRR$..........................................' - got ack for BSN=20 - got ack for BSN=19 - got ack for BSN=18 @@ -395,6 +396,7 @@ Polling is already sheduled for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW), so Sending data request: trx=0 ts=4 sapi=5 arfcn=0 fn=95 block=10 data=07 00 2a 4d 43 c0 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) downlink acknowledge - ack: (BSN=86)"RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR"(BSN=21) R=ACK I=NACK +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW) DL analysis, range=21:22, lost=0, recv=1, skipped=0, bsn=20, info='R$..............................................................' - got ack for BSN=21 - V(B): (V(A)=22)""(V(S)-1=21) A=Acked N=Nacked U=Unacked X=Resend-Unacked I=Invalid Scheduling data message at RTS for DL TFI=0 (TRX=0, TS=4) prio=4 |