llc: Calculate the average queuing delay of the LLC queues
Use a formula like it is used with TCP. This can help to make decisions about if frames should be dropped or not at the time we enqueue them. This code will store two timeval structs in fron the of the actual data and compute the average at the time of the dequeue.
This commit is contained in:
parent
a42b2ad5ed
commit
9c623892f5
26
src/llc.cpp
26
src/llc.cpp
|
@ -78,14 +78,34 @@ void gprs_llc::init()
|
||||||
{
|
{
|
||||||
INIT_LLIST_HEAD(&queue);
|
INIT_LLIST_HEAD(&queue);
|
||||||
m_queue_size = 0;
|
m_queue_size = 0;
|
||||||
|
m_avg_queue_delay = 0;
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define ALPHA 0.5f
|
||||||
|
|
||||||
struct msgb *gprs_llc::dequeue()
|
struct msgb *gprs_llc::dequeue()
|
||||||
{
|
{
|
||||||
if (m_queue_size > 0)
|
struct msgb *msg;
|
||||||
m_queue_size -= 1;
|
struct timeval *tv, tv_now, tv_result;
|
||||||
return msgb_dequeue(&queue);
|
uint32_t lifetime;
|
||||||
|
|
||||||
|
|
||||||
|
msg = msgb_dequeue(&queue);
|
||||||
|
if (!msg)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
m_queue_size -= 1;
|
||||||
|
|
||||||
|
/* take the second time */
|
||||||
|
gettimeofday(&tv_now, NULL);
|
||||||
|
tv = (struct timeval *)&msg->data[sizeof(*tv)];
|
||||||
|
timersub(&tv_now, tv, &tv_result);
|
||||||
|
|
||||||
|
lifetime = tv_result.tv_sec*1000 + tv_result.tv_usec/1000;
|
||||||
|
m_avg_queue_delay = m_avg_queue_delay * ALPHA + lifetime * (1-ALPHA);
|
||||||
|
|
||||||
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,7 @@ struct gprs_llc {
|
||||||
uint16_t m_length; /* len of current DL LLC_frame, 0 == no frame */
|
uint16_t m_length; /* len of current DL LLC_frame, 0 == no frame */
|
||||||
struct llist_head queue; /* queued LLC DL data */
|
struct llist_head queue; /* queued LLC DL data */
|
||||||
|
|
||||||
|
uint32_t m_avg_queue_delay; /* Average delay of data going through the queue */
|
||||||
size_t m_queue_size;
|
size_t m_queue_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -100,12 +100,14 @@ int gprs_rlcmac_tbf::append_data(const uint8_t ms_class,
|
||||||
/* the TBF exists, so we must write it in the queue
|
/* the TBF exists, so we must write it in the queue
|
||||||
* we prepend lifetime in front of PDU */
|
* we prepend lifetime in front of PDU */
|
||||||
struct timeval *tv;
|
struct timeval *tv;
|
||||||
struct msgb *llc_msg = msgb_alloc(len + sizeof(*tv),
|
struct msgb *llc_msg = msgb_alloc(len + sizeof(*tv) * 2,
|
||||||
"llc_pdu_queue");
|
"llc_pdu_queue");
|
||||||
if (!llc_msg)
|
if (!llc_msg)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
tv = (struct timeval *)msgb_put(llc_msg, sizeof(*tv));
|
tv = (struct timeval *)msgb_put(llc_msg, sizeof(*tv));
|
||||||
gprs_llc::calc_pdu_lifetime(bts, pdu_delay_csec, tv);
|
gprs_llc::calc_pdu_lifetime(bts, pdu_delay_csec, tv);
|
||||||
|
tv = (struct timeval *)msgb_put(llc_msg, sizeof(*tv));
|
||||||
|
gettimeofday(tv, NULL);
|
||||||
memcpy(msgb_put(llc_msg, len), data, len);
|
memcpy(msgb_put(llc_msg, len), data, len);
|
||||||
m_llc.enqueue(llc_msg);
|
m_llc.enqueue(llc_msg);
|
||||||
tbf_update_ms_class(this, ms_class);
|
tbf_update_ms_class(this, ms_class);
|
||||||
|
@ -633,6 +635,7 @@ struct msgb *gprs_rlcmac_tbf::llc_dequeue(bssgp_bvc_ctx *bctx)
|
||||||
while ((msg = m_llc.dequeue())) {
|
while ((msg = m_llc.dequeue())) {
|
||||||
tv = (struct timeval *)msg->data;
|
tv = (struct timeval *)msg->data;
|
||||||
msgb_pull(msg, sizeof(*tv));
|
msgb_pull(msg, sizeof(*tv));
|
||||||
|
msgb_pull(msg, sizeof(*tv));
|
||||||
|
|
||||||
if (gprs_llc::is_frame_expired(&tv_now, tv)) {
|
if (gprs_llc::is_frame_expired(&tv_now, tv)) {
|
||||||
LOGP(DRLCMACDL, LOGL_NOTICE, "%s Discarding LLC PDU "
|
LOGP(DRLCMACDL, LOGL_NOTICE, "%s Discarding LLC PDU "
|
||||||
|
|
Loading…
Reference in New Issue