aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJacob Erlbeck <jerlbeck@sysmocom.de>2015-07-21 17:25:52 +0200
committerJacob Erlbeck <jerlbeck@sysmocom.de>2015-07-21 19:26:23 +0200
commit66ba0844be5058032cb31c6ee3e31428417b171f (patch)
tree3dcda8f238959987e9a058f0d2b033ab3e9cf48e
parent6eed1911fd619fb594a9d1a7fc734c1f62ff2f08 (diff)
bssgp: Use measured leak rate for flow control (EXPERIMENTAL)
THIS IS EXPERIMENTAL, DO NOT USE IN PRODUCTION The leak rate sent to the SGSN does not reflect the current CS level, lost frames, and control message overhead. Use the ratio between sent blocks and successfully received bytes to derive the net leak rate. TODO: - The values are not stable, possibly resulting from interference with the sampling rate or from the interval between send and receive if they fall into different sampling intervals. - Perhaps the rate can be computed from sent data bytes / sent data frames or from the average packet size and the global nack rate.
-rw-r--r--src/gprs_bssgp_pcu.cpp41
-rw-r--r--src/gprs_bssgp_pcu.h4
-rw-r--r--src/gprs_rlcmac_sched.cpp4
-rw-r--r--src/tbf.h9
-rw-r--r--src/tbf_dl.cpp35
5 files changed, 87 insertions, 6 deletions
diff --git a/src/gprs_bssgp_pcu.cpp b/src/gprs_bssgp_pcu.cpp
index 7601b21..f909aea 100644
--- a/src/gprs_bssgp_pcu.cpp
+++ b/src/gprs_bssgp_pcu.cpp
@@ -586,6 +586,23 @@ static uint32_t get_and_reset_avg_queue_delay(void)
return avg_delay_ms;
}
+static int get_and_reset_measured_leak_rate(int num_pdch)
+{
+ int rate; /* byte per second */
+
+ if (the_pcu.queue_frames_sent == 0)
+ return -1;
+
+ /* 20ms/num_pdch is the average RLC block duration */
+ rate = the_pcu.queue_bytes_recv * 1000 * num_pdch /
+ (20 * the_pcu.queue_frames_sent);
+
+ the_pcu.queue_frames_sent = 0;
+ the_pcu.queue_bytes_recv = 0;
+
+ return rate;
+}
+
int gprs_bssgp_tx_fc_bvc(void)
{
struct gprs_rlcmac_bts *bts;
@@ -625,6 +642,20 @@ int gprs_bssgp_tx_fc_bvc(void)
ms_leak_rate = bts->fc_ms_leak_rate;
if (leak_rate == 0) {
+ int meas_rate;
+
+ if (num_pdch < 0)
+ num_pdch = count_pdch(bts);
+
+ meas_rate = get_and_reset_measured_leak_rate(num_pdch);
+ if (meas_rate > 0) {
+ leak_rate = meas_rate;
+ LOGP(DBSSGP, LOGL_DEBUG,
+ "Measured BVC leak rate = %d\n", leak_rate);
+ }
+ }
+
+ if (leak_rate == 0) {
if (num_pdch < 0)
num_pdch = count_pdch(bts);
@@ -823,6 +854,16 @@ 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)
+{
+ the_pcu.queue_bytes_recv += bytes_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 112a888..01d1cd0 100644
--- a/src/gprs_bssgp_pcu.h
+++ b/src/gprs_bssgp_pcu.h
@@ -62,6 +62,8 @@ 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;
/** callbacks below */
@@ -85,5 +87,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);
#endif // GPRS_BSSGP_PCU_H
diff --git a/src/gprs_rlcmac_sched.cpp b/src/gprs_rlcmac_sched.cpp
index dedea26..0fc252a 100644
--- a/src/gprs_rlcmac_sched.cpp
+++ b/src/gprs_rlcmac_sched.cpp
@@ -321,6 +321,10 @@ int gprs_rlcmac_rcv_rts_block(struct gprs_rlcmac_bts *bts,
if (!msg)
msg = sched_select_downlink(bts, trx, ts, fn, block_nr, pdch);
+ /* Used to calculate the net leak rate, must not include dummy messages */
+ if (msg)
+ gprs_bssgp_update_frames_sent();
+
/* Prio 3: send dummy contol message */
if (!msg)
msg = sched_dummy();
diff --git a/src/tbf.h b/src/tbf.h
index 5c198d3..0a589dc 100644
--- a/src/tbf.h
+++ b/src/tbf.h
@@ -355,6 +355,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);
@@ -363,7 +370,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 4739a50..6fbe006 100644
--- a/src/tbf_dl.cpp
+++ b/src/tbf_dl.cpp
@@ -689,7 +689,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;
@@ -697,9 +698,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())) {
@@ -713,6 +718,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) {
+ 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
@@ -722,7 +738,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';
@@ -740,6 +756,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;
@@ -755,6 +776,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) */
@@ -777,10 +799,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);
@@ -788,6 +810,9 @@ 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 calculate the net leak rate */
+ gprs_bssgp_update_bytes_received(ana_res.received_bytes);
+
/* raise V(A), if possible */
m_window.raise(m_window.move_window());