aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJacob Erlbeck <jerlbeck@sysmocom.de>2015-06-15 14:32:33 +0200
committerJacob Erlbeck <jerlbeck@sysmocom.de>2015-06-16 10:24:46 +0200
commit67728acc7a90dbf076eb179d6e3e119a4197896a (patch)
treee3489edf50b5f09b35fda23fd489944910b1369d
parent967e4dd2c357b3b3ff716fa6c77e7b7350f81711 (diff)
llc: Move storage of timestamps into gprs_llc_queue
Currently the receive and expiry timestamps are prepended to the LLC msgb before it is passed to gprs_llc_queue::enqueue(). Since this meta information should not be counted as LLC octets, the gprs_llc_queue needs to known about this (unless the correction was done in the LLC layer). This commit moves the meta information storage code into gprs_llc_queue. The meta data is now stored in the control block (cb) area of the msgb. Note that the info pointer that is returned from the dequeue method is only valid if that method returns a (non-NULL) msgb. It must not be used after that msgb has been modified or freed. Sponsored-by: On-Waves ehf
-rw-r--r--src/llc.cpp26
-rw-r--r--src/llc.h10
-rw-r--r--src/tbf_dl.cpp27
-rw-r--r--tests/llc/LlcTest.cpp73
-rw-r--r--tests/llc/LlcTest.err8
-rw-r--r--tests/llc/LlcTest.ok2
6 files changed, 96 insertions, 50 deletions
diff --git a/src/llc.cpp b/src/llc.cpp
index 8930d2c8..53a89356 100644
--- a/src/llc.cpp
+++ b/src/llc.cpp
@@ -104,10 +104,19 @@ void gprs_llc_queue::init()
m_avg_queue_delay = 0;
}
-void gprs_llc_queue::enqueue(struct msgb *llc_msg)
+void gprs_llc_queue::enqueue(struct msgb *llc_msg, const MetaInfo *info)
{
+ static const MetaInfo def_meta = {{0}};
+ MetaInfo *meta_storage;
+
+ osmo_static_assert(sizeof(*info) <= sizeof(llc_msg->cb), info_does_not_fit);
+
m_queue_size += 1;
- m_queue_octets += msgb_length(llc_msg) - 2*sizeof(struct timeval);
+ m_queue_octets += msgb_length(llc_msg);
+
+ meta_storage = (MetaInfo *)&llc_msg->cb[0];
+ *meta_storage = info ? *info : def_meta;
+
msgb_enqueue(&m_queue, llc_msg);
}
@@ -127,24 +136,29 @@ void gprs_llc_queue::clear(BTS *bts)
#define ALPHA 0.5f
-struct msgb *gprs_llc_queue::dequeue()
+struct msgb *gprs_llc_queue::dequeue(const MetaInfo **info)
{
struct msgb *msg;
struct timeval *tv, tv_now, tv_result;
uint32_t lifetime;
-
+ const MetaInfo *meta_storage;
msg = msgb_dequeue(&m_queue);
if (!msg)
return NULL;
+ meta_storage = (MetaInfo *)&msg->cb[0];
+
+ if (info)
+ *info = meta_storage;
+
m_queue_size -= 1;
- m_queue_octets -= msgb_length(msg) - 2*sizeof(struct timeval);
+ m_queue_octets -= msgb_length(msg);
/* take the second time */
gettimeofday(&tv_now, NULL);
tv = (struct timeval *)&msg->data[sizeof(*tv)];
- timersub(&tv_now, tv, &tv_result);
+ timersub(&tv_now, &meta_storage->recv_time, &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);
diff --git a/src/llc.h b/src/llc.h
index 065589db..887e210c 100644
--- a/src/llc.h
+++ b/src/llc.h
@@ -24,6 +24,7 @@ extern "C" {
#include <stdint.h>
#include <string.h>
+#include <time.h>
#define LLC_MAX_LEN 1543
@@ -63,6 +64,11 @@ struct gprs_llc {
* I store the LLC frames that come from the SGSN.
*/
struct gprs_llc_queue {
+ struct MetaInfo {
+ struct timeval recv_time;
+ struct timeval expire_time;
+ };
+
static void calc_pdu_lifetime(BTS *bts, const uint16_t pdu_delay_csec,
struct timeval *tv);
static bool is_frame_expired(const struct timeval *now,
@@ -71,8 +77,8 @@ struct gprs_llc_queue {
void init();
- void enqueue(struct msgb *llc_msg);
- struct msgb *dequeue();
+ void enqueue(struct msgb *llc_msg, const MetaInfo *info = 0);
+ struct msgb *dequeue(const MetaInfo **info = 0);
void clear(BTS *bts);
size_t size() const;
size_t octets() const;
diff --git a/src/tbf_dl.cpp b/src/tbf_dl.cpp
index 68e6fab7..853821ca 100644
--- a/src/tbf_dl.cpp
+++ b/src/tbf_dl.cpp
@@ -99,20 +99,15 @@ int gprs_rlcmac_dl_tbf::append_data(const uint8_t ms_class,
const uint8_t *data, const uint16_t len)
{
LOGP(DRLCMAC, LOGL_INFO, "%s append\n", tbf_name(this));
- /* TODO: put this path into an llc_enqueue method */
- /* the TBF exists, so we must write it in the queue
- * we prepend lifetime in front of PDU */
- struct timeval *tv;
- struct msgb *llc_msg = msgb_alloc(len + sizeof(*tv) * 2,
- "llc_pdu_queue");
+ gprs_llc_queue::MetaInfo info;
+ struct msgb *llc_msg = msgb_alloc(len, "llc_pdu_queue");
if (!llc_msg)
return -ENOMEM;
- tv = (struct timeval *)msgb_put(llc_msg, sizeof(*tv));
- gprs_llc_queue::calc_pdu_lifetime(bts, pdu_delay_csec, tv);
- tv = (struct timeval *)msgb_put(llc_msg, sizeof(*tv));
- gettimeofday(tv, NULL);
+
+ gprs_llc_queue::calc_pdu_lifetime(bts, pdu_delay_csec, &info.expire_time);
+ gettimeofday(&info.recv_time, NULL);
memcpy(msgb_put(llc_msg, len), data, len);
- llc_queue()->enqueue(llc_msg);
+ llc_queue()->enqueue(llc_msg, &info);
tbf_update_ms_class(this, ms_class);
start_llc_timer();
@@ -238,11 +233,11 @@ int gprs_rlcmac_dl_tbf::handle(struct gprs_rlcmac_bts *bts,
struct msgb *gprs_rlcmac_dl_tbf::llc_dequeue(bssgp_bvc_ctx *bctx)
{
struct msgb *msg;
- struct timeval *tv_recv, *tv_disc;
struct timeval tv_now, tv_now2;
uint32_t octets = 0, frames = 0;
struct timeval hyst_delta = {0, 0};
const unsigned keep_small_thresh = 60;
+ const gprs_llc_queue::MetaInfo *info;
if (bts_data()->llc_discard_csec)
csecs_to_timeval(bts_data()->llc_discard_csec, &hyst_delta);
@@ -250,11 +245,9 @@ struct msgb *gprs_rlcmac_dl_tbf::llc_dequeue(bssgp_bvc_ctx *bctx)
gettimeofday(&tv_now, NULL);
timeradd(&tv_now, &hyst_delta, &tv_now2);
- while ((msg = llc_queue()->dequeue())) {
- tv_disc = (struct timeval *)msg->data;
- msgb_pull(msg, sizeof(*tv_disc));
- tv_recv = (struct timeval *)msg->data;
- msgb_pull(msg, sizeof(*tv_recv));
+ while ((msg = llc_queue()->dequeue(&info))) {
+ const struct timeval *tv_disc = &info->expire_time;
+ const struct timeval *tv_recv = &info->recv_time;
gprs_bssgp_update_queue_delay(tv_recv, &tv_now);
diff --git a/tests/llc/LlcTest.cpp b/tests/llc/LlcTest.cpp
index 5cc6e6e0..de392028 100644
--- a/tests/llc/LlcTest.cpp
+++ b/tests/llc/LlcTest.cpp
@@ -41,57 +41,56 @@ extern "C" {
void *tall_pcu_ctx;
int16_t spoof_mnc = 0, spoof_mcc = 0;
-static void enqueue_data(gprs_llc_queue *queue, const uint8_t *data, size_t len)
+static void enqueue_data(gprs_llc_queue *queue, const uint8_t *data, size_t len,
+ gprs_llc_queue::MetaInfo *info = 0)
{
struct timeval *tv;
uint8_t *msg_data;
struct msgb *llc_msg = msgb_alloc(len + sizeof(*tv) * 2,
"llc_pdu_queue");
- tv = (struct timeval *)msgb_put(llc_msg, sizeof(*tv));
- memset(tv, 0, sizeof(*tv));
- tv = (struct timeval *)msgb_put(llc_msg, sizeof(*tv));
- memset(tv, 0, sizeof(*tv));
msg_data = (uint8_t *)msgb_put(llc_msg, len);
memcpy(msg_data, data, len);
- queue->enqueue(llc_msg);
+ queue->enqueue(llc_msg, info);
}
-static void dequeue_and_check(gprs_llc_queue *queue, const uint8_t *exp_data, size_t len)
+static void dequeue_and_check(gprs_llc_queue *queue, const uint8_t *exp_data,
+ size_t len, const gprs_llc_queue::MetaInfo *exp_info = 0)
{
struct msgb *llc_msg;
uint8_t *msg_data;
+ const gprs_llc_queue::MetaInfo *info_res;
- llc_msg = queue->dequeue();
+ llc_msg = queue->dequeue(&info_res);
OSMO_ASSERT(llc_msg != NULL);
- fprintf(stderr, "dequeued msg, length %d, data %s\n",
- msgb_length(llc_msg), msgb_hexdump(llc_msg));
-
- OSMO_ASSERT(msgb_length(llc_msg) >= 2*sizeof(struct timeval));
- msgb_pull(llc_msg, sizeof(struct timeval));
- msgb_pull(llc_msg, sizeof(struct timeval));
-
- fprintf(stderr, "LLC message, length %d (expected %d)\n",
- msgb_length(llc_msg), len);
+ fprintf(stderr, "dequeued msg, length %d (expected %d), data %s\n",
+ msgb_length(llc_msg), len, msgb_hexdump(llc_msg));
OSMO_ASSERT(msgb_length(llc_msg) == len);
msg_data = msgb_data(llc_msg);
OSMO_ASSERT(memcmp(msg_data, exp_data, len) == 0);
+
+ if (exp_info)
+ OSMO_ASSERT(memcmp(exp_info, info_res, sizeof(*exp_info)) == 0);
+
msgb_free(llc_msg);
}
-static void enqueue_data(gprs_llc_queue *queue, const char *message)
+static void enqueue_data(gprs_llc_queue *queue, const char *message,
+ gprs_llc_queue::MetaInfo *info = 0)
{
- enqueue_data(queue, (uint8_t *)(message), strlen(message));
+ enqueue_data(queue, (uint8_t *)(message), strlen(message), info);
}
-static void dequeue_and_check(gprs_llc_queue *queue, const char *exp_message)
+static void dequeue_and_check(gprs_llc_queue *queue, const char *exp_message,
+ const gprs_llc_queue::MetaInfo *exp_info = 0)
{
- dequeue_and_check(queue, (uint8_t *)(exp_message), strlen(exp_message));
+ dequeue_and_check(queue,
+ (uint8_t *)(exp_message), strlen(exp_message), exp_info);
}
static void test_llc_queue()
@@ -131,6 +130,37 @@ static void test_llc_queue()
printf("=== end %s ===\n", __func__);
}
+static void test_llc_meta()
+{
+ gprs_llc_queue queue;
+ gprs_llc_queue::MetaInfo info1 = {
+ .recv_time = {123456777, 123456},
+ .expire_time = {123456789, 987654},
+ };
+ gprs_llc_queue::MetaInfo info2 = {
+ .recv_time = {987654321, 547352},
+ .expire_time = {987654327, 867252},
+ };
+
+ printf("=== start %s ===\n", __func__);
+
+ queue.init();
+ OSMO_ASSERT(queue.size() == 0);
+ OSMO_ASSERT(queue.octets() == 0);
+
+ enqueue_data(&queue, "LLC message 1", &info1);
+ enqueue_data(&queue, "LLC message 2", &info2);
+
+ dequeue_and_check(&queue, "LLC message 1", &info1);
+ dequeue_and_check(&queue, "LLC message 2", &info2);
+
+ queue.clear(NULL);
+ OSMO_ASSERT(queue.size() == 0);
+ OSMO_ASSERT(queue.octets() == 0);
+
+ printf("=== end %s ===\n", __func__);
+}
+
static const struct log_info_cat default_categories[] = {
{"DPCU", "", "GPRS Packet Control Unit (PCU)", LOGL_INFO, 1},
};
@@ -165,6 +195,7 @@ int main(int argc, char **argv)
pcu_vty_init(&debug_log_info);
test_llc_queue();
+ test_llc_meta();
if (getenv("TALLOC_REPORT_FULL"))
talloc_report_full(tall_pcu_ctx, stderr);
diff --git a/tests/llc/LlcTest.err b/tests/llc/LlcTest.err
index 5ebb3682..b28fe1df 100644
--- a/tests/llc/LlcTest.err
+++ b/tests/llc/LlcTest.err
@@ -1,4 +1,4 @@
-dequeued msg, length 27, data 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 4c 4c 43 20 6d 65 73 73 61 67 65
-LLC message, length 11 (expected 11)
-dequeued msg, length 33, data 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 6f 74 68 65 72 20 4c 4c 43 20 6d 65 73 73 61 67 65
-LLC message, length 17 (expected 17)
+dequeued msg, length 11 (expected 11), data 4c 4c 43 20 6d 65 73 73 61 67 65
+dequeued msg, length 17 (expected 17), data 6f 74 68 65 72 20 4c 4c 43 20 6d 65 73 73 61 67 65
+dequeued msg, length 13 (expected 13), data 4c 4c 43 20 6d 65 73 73 61 67 65 20 31
+dequeued msg, length 13 (expected 13), data 4c 4c 43 20 6d 65 73 73 61 67 65 20 32
diff --git a/tests/llc/LlcTest.ok b/tests/llc/LlcTest.ok
index 79e23cd4..8a5f2354 100644
--- a/tests/llc/LlcTest.ok
+++ b/tests/llc/LlcTest.ok
@@ -1,2 +1,4 @@
=== start test_llc_queue ===
=== end test_llc_queue ===
+=== start test_llc_meta ===
+=== end test_llc_meta ===