llc: Convert to C
There's no real reason (other than historical) why code in llc should be
kept as c++ code. Let's rewrite it as C so that it can be included by
existing C code without having to add C->C++ shim, ifdefs all around,
etc.
This simplifies code and easies modification/improvement of the related
objects.
Change-Id: I250680ba581167d7398b2f734769c756cbb61c48
diff --git a/src/Makefile.am b/src/Makefile.am
index 25fdab2..fedc96f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -73,7 +73,7 @@
encoding.cpp \
sba.c \
decoding.cpp \
- llc.cpp \
+ llc.c \
rlc.cpp \
osmobts_sock.c \
gprs_codel.c \
diff --git a/src/llc.cpp b/src/llc.c
similarity index 69%
rename from src/llc.cpp
rename to src/llc.c
index 5cf2213..700585a 100644
--- a/src/llc.cpp
+++ b/src/llc.c
@@ -15,32 +15,36 @@
* GNU General Public License for more details.
*/
-#include <bts.h>
#include <stdio.h>
-extern "C" {
#include <osmocom/core/msgb.h>
-}
+#include "bts.h"
#include "pcu_utils.h"
+#include "llc.h"
+
+void llc_init(struct gprs_llc *llc)
+{
+ llc_reset(llc);
+}
/* reset LLC frame */
-void gprs_llc::reset()
+void llc_reset(struct gprs_llc *llc)
{
- index = 0;
- length = 0;
+ llc->index = 0;
+ llc->length = 0;
- memset(frame, 0x42, sizeof(frame));
+ memset(llc->frame, 0x42, sizeof(llc->frame));
}
-void gprs_llc::reset_frame_space()
+void llc_reset_frame_space(struct gprs_llc *llc)
{
- index = 0;
+ llc->index = 0;
}
/* Put an Unconfirmed Information (UI) Dummy command, see GSM 44.064, 6.4.2.2 */
-void gprs_llc::put_dummy_frame(size_t req_len)
+void llc_put_dummy_frame(struct gprs_llc *llc, size_t req_len)
{
/* The shortest dummy command (the spec requests at least 6 octets) */
static const uint8_t llc_dummy_command[] = {
@@ -48,39 +52,34 @@
};
static const size_t max_dummy_command_len = 79;
- put_frame(llc_dummy_command, sizeof(llc_dummy_command));
+ llc_put_frame(llc, llc_dummy_command, sizeof(llc_dummy_command));
if (req_len > max_dummy_command_len)
req_len = max_dummy_command_len;
/* Add further stuffing, if the requested length exceeds the minimum
* dummy command length */
- if (length < req_len) {
- memset(&frame[length], 0x2b, req_len - length);
- length = req_len;
+ if (llc->length < req_len) {
+ memset(&llc->frame[llc->length], 0x2b, req_len - llc->length);
+ llc->length = req_len;
}
}
-void gprs_llc::put_frame(const uint8_t *data, size_t len)
+void llc_put_frame(struct gprs_llc *llc, const uint8_t *data, size_t len)
{
/* only put frames when we are empty */
- OSMO_ASSERT(index == 0 && length == 0);
- append_frame(data, len);
+ OSMO_ASSERT(llc->index == 0 && llc->length == 0);
+ llc_append_frame(llc, data, len);
}
-void gprs_llc::append_frame(const uint8_t *data, size_t len)
+void llc_append_frame(struct gprs_llc *llc, const uint8_t *data, size_t len)
{
/* TODO: bounds check */
- memcpy(frame + length, data, len);
- length += len;
+ memcpy(llc->frame + llc->length, data, len);
+ llc->length += len;
}
-void gprs_llc::init()
-{
- reset();
-}
-
-bool gprs_llc::is_user_data_frame(uint8_t *data, size_t len)
+bool llc_is_user_data_frame(const uint8_t *data, size_t len)
{
if (len < 2)
return false;
@@ -104,20 +103,20 @@
}
-void gprs_llc_queue::enqueue(struct msgb *llc_msg, const struct timespec *expire_time)
+void llc_queue_enqueue(struct gprs_llc_queue *q, struct msgb *llc_msg, const struct timespec *expire_time)
{
- MetaInfo *meta_storage;
+ struct MetaInfo *meta_storage;
osmo_static_assert(sizeof(*meta_storage) <= sizeof(llc_msg->cb), info_does_not_fit);
- queue_size += 1;
- queue_octets += msgb_length(llc_msg);
+ q->queue_size += 1;
+ q->queue_octets += msgb_length(llc_msg);
- meta_storage = (MetaInfo *)&llc_msg->cb[0];
+ meta_storage = (struct MetaInfo *)&llc_msg->cb[0];
osmo_clock_gettime(CLOCK_MONOTONIC, &meta_storage->recv_time);
meta_storage->expire_time = *expire_time;
- msgb_enqueue(&queue, llc_msg);
+ msgb_enqueue(&q->queue, llc_msg);
}
void llc_queue_clear(struct gprs_llc_queue *q, struct gprs_rlcmac_bts *bts)
@@ -159,8 +158,8 @@
msg = msg1;
msg1 = NULL;
} else {
- const MetaInfo *mi1 = (MetaInfo *)&msg1->cb[0];
- const MetaInfo *mi2 = (MetaInfo *)&msg2->cb[0];
+ 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;
@@ -189,24 +188,24 @@
#define ALPHA 0.5f
-struct msgb *gprs_llc_queue::dequeue(const MetaInfo **info)
+struct msgb *llc_queue_dequeue(struct gprs_llc_queue *q, const struct MetaInfo **info)
{
struct msgb *msg;
struct timespec *tv, tv_now, tv_result;
uint32_t lifetime;
- const MetaInfo *meta_storage;
+ const struct MetaInfo *meta_storage;
- msg = msgb_dequeue(&queue);
+ msg = msgb_dequeue(&q->queue);
if (!msg)
return NULL;
- meta_storage = (MetaInfo *)&msg->cb[0];
+ meta_storage = (struct MetaInfo *)&msg->cb[0];
if (info)
*info = meta_storage;
- queue_size -= 1;
- queue_octets -= msgb_length(msg);
+ q->queue_size -= 1;
+ q->queue_octets -= msgb_length(msg);
/* take the second time */
osmo_clock_gettime(CLOCK_MONOTONIC, &tv_now);
@@ -214,12 +213,12 @@
timespecsub(&tv_now, &meta_storage->recv_time, &tv_result);
lifetime = tv_result.tv_sec*1000 + tv_result.tv_nsec/1000000;
- avg_queue_delay = avg_queue_delay * ALPHA + lifetime * (1-ALPHA);
+ q->avg_queue_delay = q->avg_queue_delay * ALPHA + lifetime * (1-ALPHA);
return msg;
}
-void gprs_llc_queue::calc_pdu_lifetime(struct gprs_rlcmac_bts *bts, const uint16_t pdu_delay_csec, struct timespec *tv)
+void llc_queue_calc_pdu_lifetime(struct gprs_rlcmac_bts *bts, const uint16_t pdu_delay_csec, struct timespec *tv)
{
uint16_t delay_csec;
if (bts->pcu->vty.force_llc_lifetime)
@@ -241,8 +240,7 @@
timespecadd(&now, &csec, tv);
}
-bool gprs_llc_queue::is_frame_expired(const struct timespec *tv_now,
- const struct timespec *tv)
+bool llc_queue_is_frame_expired(const struct timespec *tv_now, const struct timespec *tv)
{
/* Timeout is infinite */
if (tv->tv_sec == 0 && tv->tv_nsec == 0)
diff --git a/src/llc.h b/src/llc.h
index e7548d4..a371b68 100644
--- a/src/llc.h
+++ b/src/llc.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2013 by Holger Hans Peter Freyther
+ * Copyright (C) 2022 by by Sysmocom s.f.m.c. GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -17,15 +18,14 @@
#ifdef __cplusplus
extern "C" {
#endif
- #include <osmocom/core/linuxlist.h>
-#ifdef __cplusplus
-}
-#endif
#include <stdint.h>
#include <string.h>
#include <time.h>
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/core/msgb.h>
+
#define LLC_MAX_LEN 1543
struct gprs_rlcmac_bts;
@@ -34,23 +34,19 @@
* I represent the LLC data to a MS
*/
struct gprs_llc {
-
-#ifdef __cplusplus
- static bool is_user_data_frame(uint8_t *data, size_t len);
-
- void init();
- void reset();
- void reset_frame_space();
-
- void put_frame(const uint8_t *data, size_t len);
- void put_dummy_frame(size_t req_len);
- void append_frame(const uint8_t *data, size_t len);
-#endif
-
uint8_t frame[LLC_MAX_LEN]; /* current DL or UL frame */
uint16_t index; /* current write/read position of frame */
uint16_t length; /* len of current DL LLC_frame, 0 == no frame */
};
+bool llc_is_user_data_frame(const uint8_t *data, size_t len);
+
+void llc_init(struct gprs_llc *llc);
+void llc_reset(struct gprs_llc *llc);
+void llc_reset_frame_space(struct gprs_llc *llc);
+
+void llc_put_frame(struct gprs_llc *llc, const uint8_t *data, size_t len);
+void llc_put_dummy_frame(struct gprs_llc *llc, size_t req_len);
+void llc_append_frame(struct gprs_llc *llc, const uint8_t *data, size_t len);
struct MetaInfo {
struct timespec recv_time;
@@ -60,28 +56,21 @@
* I store the LLC frames that come from the SGSN.
*/
struct gprs_llc_queue {
-#ifdef __cplusplus
- static void calc_pdu_lifetime(struct gprs_rlcmac_bts *bts, const uint16_t pdu_delay_csec,
- struct timespec *tv);
- static bool is_frame_expired(const struct timespec *now,
- const struct timespec *tv);
- static bool is_user_data_frame(uint8_t *data, size_t len);
-
- void enqueue(struct msgb *llc_msg, const struct timespec *expire_time);
- struct msgb *dequeue(const MetaInfo **info = 0);
-#endif
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 */
};
-#ifdef __cplusplus
-extern "C" {
-#endif
+void llc_queue_calc_pdu_lifetime(struct gprs_rlcmac_bts *bts, const uint16_t pdu_delay_csec,
+ struct timespec *tv);
+bool llc_queue_is_frame_expired(const struct timespec *tv_now, const struct timespec *tv);
+
void llc_queue_init(struct gprs_llc_queue *q);
void llc_queue_clear(struct gprs_llc_queue *q, struct gprs_rlcmac_bts *bts);
void llc_queue_move_and_merge(struct gprs_llc_queue *q, struct gprs_llc_queue *o);
+void llc_queue_enqueue(struct gprs_llc_queue *q, struct msgb *llc_msg, const struct timespec *expire_time);
+struct msgb *llc_queue_dequeue(struct gprs_llc_queue *q, const struct MetaInfo **info);
static inline uint16_t llc_chunk_size(const struct gprs_llc *llc)
{
diff --git a/src/tbf.cpp b/src/tbf.cpp
index c2eeb89..2c68ede 100644
--- a/src/tbf.cpp
+++ b/src/tbf.cpp
@@ -130,7 +130,7 @@
OSMO_ASSERT(dl_ass_fsm.fi);
m_rlc.init();
- m_llc.init();
+ llc_init(&m_llc);
m_name_buf[0] = '\0';
diff --git a/src/tbf_dl.cpp b/src/tbf_dl.cpp
index ec455c1..01b8f68 100644
--- a/src/tbf_dl.cpp
+++ b/src/tbf_dl.cpp
@@ -217,9 +217,9 @@
if (!llc_msg)
return -ENOMEM;
- gprs_llc_queue::calc_pdu_lifetime(bts, pdu_delay_csec, &expire_time);
+ llc_queue_calc_pdu_lifetime(bts, pdu_delay_csec, &expire_time);
memcpy(msgb_put(llc_msg, len), data, len);
- llc_queue()->enqueue(llc_msg, &expire_time);
+ llc_queue_enqueue(llc_queue(), llc_msg, &expire_time);
start_llc_timer();
if (state_is(TBF_ST_WAIT_RELEASE)) {
@@ -358,7 +358,7 @@
osmo_clock_gettime(CLOCK_MONOTONIC, &tv_now);
timespecadd(&tv_now, &hyst_delta, &tv_now2);
- while ((msg = llc_queue()->dequeue(&info))) {
+ while ((msg = llc_queue_dequeue(llc_queue(), &info))) {
const struct timespec *tv_disc = &info->expire_time;
const struct timespec *tv_recv = &info->recv_time;
@@ -372,11 +372,11 @@
}
/* Is the age below the low water mark? */
- if (!gprs_llc_queue::is_frame_expired(&tv_now2, tv_disc))
+ if (!llc_queue_is_frame_expired(&tv_now2, tv_disc))
break;
/* Is the age below the high water mark */
- if (!gprs_llc_queue::is_frame_expired(&tv_now, tv_disc)) {
+ if (!llc_queue_is_frame_expired(&tv_now, tv_disc)) {
/* Has the previous message not been dropped? */
if (frames == 0)
break;
@@ -391,7 +391,7 @@
break;
/* Is it a GMM message? */
- if (!gprs_llc::is_user_data_frame(msg->data, msg->len))
+ if (!llc_is_user_data_frame(msg->data, msg->len))
break;
}
@@ -634,7 +634,7 @@
LOGPTBFDL(this, LOGL_DEBUG, "Dequeue next LLC (len=%d)\n", msg->len);
- m_llc.put_frame(msg->data, msg->len);
+ llc_put_frame(&m_llc, msg->data, msg->len);
bts_do_rate_ctr_inc(bts, CTR_LLC_FRAME_SCHED);
msgb_free(msg);
m_last_dl_drained_fn = -1;
@@ -726,7 +726,7 @@
* "Delayed release of downlink Temporary Block Flow" */
/* A header will need to by added, so we just need
* space-1 octets */
- m_llc.put_dummy_frame(space - 1);
+ llc_put_dummy_frame(&m_llc, space - 1);
LOGPTBFDL(this, LOGL_DEBUG,
"Empty chunk, added LLC dummy command of size %d, drained_since=%d\n",
@@ -747,7 +747,7 @@
LOGPTBFDL(this, LOGL_DEBUG, "Complete DL frame, len=%d\n", llc_frame_length(&m_llc));
gprs_rlcmac_dl_bw(this, llc_frame_length(&m_llc));
bts_do_rate_ctr_add(bts, CTR_LLC_DL_BYTES, llc_frame_length(&m_llc));
- m_llc.reset();
+ llc_reset(&m_llc);
if (is_final) {
request_dl_ack();
diff --git a/src/tbf_ul.cpp b/src/tbf_ul.cpp
index 305daaa..21a7a76 100644
--- a/src/tbf_ul.cpp
+++ b/src/tbf_ul.cpp
@@ -283,7 +283,7 @@
i + 1, frame->offset, frame->length,
frame->is_complete);
- m_llc.append_frame(data + frame->offset, frame->length);
+ llc_append_frame(&m_llc, data + frame->offset, frame->length);
llc_consume(&m_llc, frame->length);
}
@@ -292,7 +292,7 @@
LOGPTBFUL(this, LOGL_DEBUG, "complete UL frame len=%d\n", llc_frame_length(&m_llc));
snd_ul_ud();
bts_do_rate_ctr_add(bts, CTR_LLC_UL_BYTES, llc_frame_length(&m_llc));
- m_llc.reset();
+ llc_reset(&m_llc);
}
}
@@ -544,7 +544,7 @@
LOGP(DBSSGP, LOGL_INFO, "LLC [PCU -> SGSN] %s len=%d\n", tbf_name(this), llc_frame_length(&m_llc));
if (!bctx) {
LOGP(DBSSGP, LOGL_ERROR, "No bctx\n");
- m_llc.reset_frame_space();
+ llc_reset_frame_space(&m_llc);
return -EIO;
}
@@ -556,7 +556,7 @@
qos_profile[2] = QOS_PROFILE;
bssgp_tx_ul_ud(bctx, tlli(), qos_profile, llc_pdu);
- m_llc.reset_frame_space();
+ llc_reset_frame_space(&m_llc);
return 0;
}