pespin has uploaded this change for review.

View Change

WIP: llc: schedule frames to MS based on SAPI priority

Related: OS#5508
Related: SYS#5908
Change-Id: Ie8bd91eeac4fa7487d4f11b808dea95737041c7e
---
M src/llc.c
M src/llc.h
2 files changed, 91 insertions(+), 37 deletions(-)

git pull ssh://gerrit.osmocom.org:29418/osmo-pcu refs/changes/27/27627/1
diff --git a/src/llc.c b/src/llc.c
index 700585a..d333920 100644
--- a/src/llc.c
+++ b/src/llc.c
@@ -96,19 +96,40 @@

void llc_queue_init(struct gprs_llc_queue *q)
{
- INIT_LLIST_HEAD(&q->queue);
+ int i;
+
q->queue_size = 0;
q->queue_octets = 0;
q->avg_queue_delay = 0;
+ for (i = 0; i < ARRAY_SIZE(q->queue); i++)
+ INIT_LLIST_HEAD(&q->queue[i]);
}


+static enum gprs_llc_queue_prio llc_sapi2prio(uint8_t sapi)
+{
+ switch (sapi) {
+ case 1:
+ return LLC_QUEUE_PRIO_GMM;
+ case 2:
+ case 7:
+ case 8:
+ return LLC_QUEUE_PRIO_TOM_SMS;
+ default:
+ return LLC_QUEUE_PRIO_OTHER;
+ }
+}
+
void llc_queue_enqueue(struct gprs_llc_queue *q, struct msgb *llc_msg, const struct timespec *expire_time)
{
struct MetaInfo *meta_storage;
+ struct gprs_llc_hdr *llc_hdr = (struct gprs_llc_hdr *)msgb_data(llc_msg);
+ enum gprs_llc_queue_prio prio;

osmo_static_assert(sizeof(*meta_storage) <= sizeof(llc_msg->cb), info_does_not_fit);

+ prio = llc_sapi2prio(llc_hdr->sapi);
+
q->queue_size += 1;
q->queue_octets += msgb_length(llc_msg);

@@ -116,17 +137,20 @@
osmo_clock_gettime(CLOCK_MONOTONIC, &meta_storage->recv_time);
meta_storage->expire_time = *expire_time;

- msgb_enqueue(&q->queue, llc_msg);
+ msgb_enqueue(&q->queue[prio], llc_msg);
}

void llc_queue_clear(struct gprs_llc_queue *q, struct gprs_rlcmac_bts *bts)
{
struct msgb *msg;
+ unsigned int i;

- while ((msg = msgb_dequeue(&q->queue))) {
- if (bts)
- bts_do_rate_ctr_inc(bts, CTR_LLC_FRAME_DROPPED);
- msgb_free(msg);
+ for (i = 0; i < ARRAY_SIZE(q->queue); i++) {
+ while ((msg = msgb_dequeue(&q->queue[i]))) {
+ if (bts)
+ bts_do_rate_ctr_inc(bts, CTR_LLC_FRAME_DROPPED);
+ msgb_free(msg);
+ }
}

q->queue_size = 0;
@@ -137,51 +161,53 @@
{
struct msgb *msg, *msg1 = NULL, *msg2 = NULL;
struct llist_head new_queue;
+ unsigned int i;
size_t queue_size = 0;
size_t queue_octets = 0;
INIT_LLIST_HEAD(&new_queue);

- while (1) {
- if (msg1 == NULL)
- msg1 = msgb_dequeue(&q->queue);
+ for (i = 0; i < ARRAY_SIZE(q->queue); i++) {
+ while (1) {
+ if (msg1 == NULL)
+ msg1 = msgb_dequeue(&q->queue[i]);

- if (msg2 == NULL)
- msg2 = msgb_dequeue(&o->queue);
+ if (msg2 == NULL)
+ msg2 = msgb_dequeue(&o->queue[i]);

- if (msg1 == NULL && msg2 == NULL)
- break;
+ if (msg1 == NULL && msg2 == NULL)
+ break;

- if (msg1 == NULL) {
- msg = msg2;
- msg2 = NULL;
- } else if (msg2 == NULL) {
- msg = msg1;
- msg1 = NULL;
- } else {
- const struct MetaInfo *mi1 = (struct MetaInfo *)&msg1->cb[0];
- const struct MetaInfo *mi2 = (struct MetaInfo *)&msg2->cb[0];
-
- if (timespeccmp(&mi2->recv_time, &mi1->recv_time, >)) {
+ if (msg1 == NULL) {
+ msg = msg2;
+ msg2 = NULL;
+ } else if (msg2 == NULL) {
msg = msg1;
msg1 = NULL;
} else {
- msg = msg2;
- msg2 = NULL;
+ const struct MetaInfo *mi1 = (struct MetaInfo *)&msg1->cb[0];
+ const struct MetaInfo *mi2 = (struct MetaInfo *)&msg2->cb[0];
+
+ if (timespeccmp(&mi2->recv_time, &mi1->recv_time, >)) {
+ msg = msg1;
+ msg1 = NULL;
+ } else {
+ msg = msg2;
+ msg2 = NULL;
+ }
}
+
+ msgb_enqueue(&new_queue, msg);
+ queue_size += 1;
+ queue_octets += msgb_length(msg);
}

- msgb_enqueue(&new_queue, msg);
- queue_size += 1;
- queue_octets += msgb_length(msg);
+ OSMO_ASSERT(llist_empty(&q->queue[i]));
+ OSMO_ASSERT(llist_empty(&o->queue[i]));
+ llist_splice_init(&new_queue, &q->queue[i]);
}

- OSMO_ASSERT(llist_empty(&q->queue));
- OSMO_ASSERT(llist_empty(&o->queue));
-
o->queue_size = 0;
o->queue_octets = 0;
-
- llist_splice_init(&new_queue, &q->queue);
q->queue_size = queue_size;
q->queue_octets = queue_octets;
}
@@ -193,9 +219,13 @@
struct msgb *msg;
struct timespec *tv, tv_now, tv_result;
uint32_t lifetime;
+ unsigned int i;
const struct MetaInfo *meta_storage;

- msg = msgb_dequeue(&q->queue);
+ for (i = 0; i < ARRAY_SIZE(q->queue); i++) {
+ if ((msg = msgb_dequeue(&q->queue[i])))
+ break;
+ }
if (!msg)
return NULL;

diff --git a/src/llc.h b/src/llc.h
index bd542c0..035fe77 100644
--- a/src/llc.h
+++ b/src/llc.h
@@ -1,4 +1,4 @@
-/*
+/* 3GPP TS 44.064
* Copyright (C) 2013 by Holger Hans Peter Freyther
* Copyright (C) 2022 by by Sysmocom s.f.m.c. GmbH
*
@@ -23,13 +23,31 @@
#include <string.h>
#include <time.h>

+#include <osmocom/core/endian.h>
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/msgb.h>
+#include <osmocom/core/endian.h>

#define LLC_MAX_LEN 1543

struct gprs_rlcmac_bts;

+struct gprs_llc_hdr {
+#if OSMO_IS_LITTLE_ENDIAN
+ union { /* 5.2, 6.2.0 */
+ uint8_t address;
+ uint8_t sapi:4, unused:2, c_r:1, pd:1;
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */
+ union {
+ uint8_t address;
+ uint8_t pd:1, c_r:1, unused:2, sapi:4;
+#endif
+ };
+ uint8_t control[0];
+/* TODO: fix for big endian/little endian */
+} __attribute__ ((packed));
+
/**
* I represent the LLC data to a MS
*/
@@ -87,11 +105,17 @@
/**
* I store the LLC frames that come from the SGSN.
*/
+enum gprs_llc_queue_prio { /* lowest value has highest prio */
+ LLC_QUEUE_PRIO_GMM = 0, /* SAPI 1 */
+ LLC_QUEUE_PRIO_TOM_SMS, /* SAPI 2,7,8 */
+ LLC_QUEUE_PRIO_OTHER, /* Other SAPIs */
+ _LLC_QUEUE_PRIO_SIZE /* used to calculate size of enum */
+};
struct gprs_llc_queue {
uint32_t avg_queue_delay; /* Average delay of data going through the queue */
size_t queue_size;
size_t queue_octets;
- struct llist_head queue; /* queued LLC DL data */
+ struct llist_head queue[_LLC_QUEUE_PRIO_SIZE]; /* queued LLC DL data. See enum gprs_llc_queue_prio. */
};

void llc_queue_calc_pdu_lifetime(struct gprs_rlcmac_bts *bts, const uint16_t pdu_delay_csec,

To view, visit change 27627. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: osmo-pcu
Gerrit-Branch: master
Gerrit-Change-Id: Ie8bd91eeac4fa7487d4f11b808dea95737041c7e
Gerrit-Change-Number: 27627
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <pespin@sysmocom.de>
Gerrit-MessageType: newchange