aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJacob Erlbeck <jerlbeck@sysmocom.de>2015-05-29 10:37:09 +0200
committerJacob Erlbeck <jerlbeck@sysmocom.de>2015-06-08 09:35:11 +0200
commit6dbe822062d54a6c765c6fa7e2c6b79a5dff29b1 (patch)
tree7f1f703d29edfc1b03b3e0c4d70123b7571c9e0c
parentb3f713bd7be2af9bf7c3168099d35df089020164 (diff)
llc: Separate LLC queue handling from gprs_llc
Currently the gprs_llc class handles both LLC queueing and the partition into smaller pieces for RLC/MAC encapsulation. This hinders the separation of TBF and MS related data, since LLC queueing belongs to the MS related code while the RLC/MAC encoding/decoding belongs to the TBF layer. This commits takes the LLC queueing related methods and members and puts them into a new class gprs_llc_queue. It puts the queueing object into gprs_rlcmac_tbf and adds accessor functions. The implementation in tbf.cpp and tbf_dl.cpp is adapted accordingly. Ticket: #1674 Sponsored-by: On-Waves ehf
-rw-r--r--src/llc.cpp76
-rw-r--r--src/llc.h32
-rw-r--r--src/tbf.cpp3
-rw-r--r--src/tbf.h14
-rw-r--r--src/tbf_dl.cpp20
5 files changed, 91 insertions, 54 deletions
diff --git a/src/llc.cpp b/src/llc.cpp
index 9c5581fb..09242a55 100644
--- a/src/llc.cpp
+++ b/src/llc.cpp
@@ -42,12 +42,6 @@ void gprs_llc::reset_frame_space()
m_index = 0;
}
-void gprs_llc::enqueue(struct msgb *llc_msg)
-{
- m_queue_size += 1;
- msgb_enqueue(&queue, llc_msg);
-}
-
/* 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)
{
@@ -82,36 +76,62 @@ void gprs_llc::append_frame(const uint8_t *data, size_t len)
m_length += len;
}
-void gprs_llc::clear(BTS *bts)
+void gprs_llc::init()
{
- struct msgb *msg;
+ reset();
+}
- while ((msg = msgb_dequeue(&queue))) {
- bts->llc_dropped_frame();
- msgb_free(msg);
- }
+bool gprs_llc::is_user_data_frame(uint8_t *data, size_t len)
+{
+ if (len < 2)
+ return false;
- m_queue_size = 0;
+ if ((data[0] & 0x0f) == 1 /* GPRS_SAPI_GMM */)
+ return false;
+
+ if ((data[0] & 0x0e) != 0xc0 /* LLC UI */)
+ /* It is not an LLC UI frame */
+ return false;
+
+ return true;
}
-void gprs_llc::init()
+void gprs_llc_queue::init()
{
- INIT_LLIST_HEAD(&queue);
+ INIT_LLIST_HEAD(&m_queue);
m_queue_size = 0;
m_avg_queue_delay = 0;
- reset();
+}
+
+void gprs_llc_queue::enqueue(struct msgb *llc_msg)
+{
+ m_queue_size += 1;
+ msgb_enqueue(&m_queue, llc_msg);
+}
+
+void gprs_llc_queue::clear(BTS *bts)
+{
+ struct msgb *msg;
+
+ while ((msg = msgb_dequeue(&m_queue))) {
+ if (bts)
+ bts->llc_dropped_frame();
+ msgb_free(msg);
+ }
+
+ m_queue_size = 0;
}
#define ALPHA 0.5f
-struct msgb *gprs_llc::dequeue()
+struct msgb *gprs_llc_queue::dequeue()
{
struct msgb *msg;
struct timeval *tv, tv_now, tv_result;
uint32_t lifetime;
- msg = msgb_dequeue(&queue);
+ msg = msgb_dequeue(&m_queue);
if (!msg)
return NULL;
@@ -128,8 +148,7 @@ struct msgb *gprs_llc::dequeue()
return msg;
}
-
-void gprs_llc::calc_pdu_lifetime(BTS *bts, const uint16_t pdu_delay_csec, struct timeval *tv)
+void gprs_llc_queue::calc_pdu_lifetime(BTS *bts, const uint16_t pdu_delay_csec, struct timeval *tv)
{
uint16_t delay_csec;
if (bts->bts_data()->force_llc_lifetime)
@@ -152,7 +171,7 @@ void gprs_llc::calc_pdu_lifetime(BTS *bts, const uint16_t pdu_delay_csec, struct
timeradd(&now, &csec, tv);
}
-bool gprs_llc::is_frame_expired(struct timeval *tv_now, struct timeval *tv)
+bool gprs_llc_queue::is_frame_expired(struct timeval *tv_now, struct timeval *tv)
{
/* Timeout is infinite */
if (tv->tv_sec == 0 && tv->tv_usec == 0)
@@ -160,18 +179,3 @@ bool gprs_llc::is_frame_expired(struct timeval *tv_now, struct timeval *tv)
return timercmp(tv_now, tv, >);
}
-
-bool gprs_llc::is_user_data_frame(uint8_t *data, size_t len)
-{
- if (len < 2)
- return false;
-
- if ((data[0] & 0x0f) == 1 /* GPRS_SAPI_GMM */)
- return false;
-
- if ((data[0] & 0x0e) != 0xc0 /* LLC UI */)
- /* It is not an LLC UI frame */
- return false;
-
- return true;
-}
diff --git a/src/llc.h b/src/llc.h
index 11a0c7ed..251712a3 100644
--- a/src/llc.h
+++ b/src/llc.h
@@ -27,24 +27,18 @@
* I represent the LLC data to a MS
*/
struct gprs_llc {
- static void calc_pdu_lifetime(BTS *bts, const uint16_t pdu_delay_csec, struct timeval *tv);
- static bool is_frame_expired(struct timeval *now, struct timeval *tv);
static bool is_user_data_frame(uint8_t *data, size_t len);
void init();
void reset();
void reset_frame_space();
- void enqueue(struct msgb *llc_msg);
- struct msgb *dequeue();
-
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);
void consume(size_t len);
void consume(uint8_t *data, size_t len);
- void clear(BTS *bts);
uint16_t chunk_size() const;
uint16_t remaining_space() const;
@@ -55,12 +49,31 @@ struct gprs_llc {
uint8_t frame[LLC_MAX_LEN]; /* current DL or UL frame */
uint16_t m_index; /* current write/read position of frame */
uint16_t m_length; /* len of current DL LLC_frame, 0 == no frame */
- struct llist_head queue; /* queued LLC DL data */
+};
+
+/**
+ * I store the LLC frames that come from the SGSN.
+ */
+struct gprs_llc_queue {
+ static void calc_pdu_lifetime(BTS *bts, const uint16_t pdu_delay_csec, struct timeval *tv);
+ static bool is_frame_expired(struct timeval *now, struct timeval *tv);
+ static bool is_user_data_frame(uint8_t *data, size_t len);
+
+ void init();
+
+ void enqueue(struct msgb *llc_msg);
+ struct msgb *dequeue();
+ void clear(BTS *bts);
+ size_t size() const;
+private:
uint32_t m_avg_queue_delay; /* Average delay of data going through the queue */
size_t m_queue_size;
+ struct llist_head m_queue; /* queued LLC DL data */
+
};
+
inline uint16_t gprs_llc::chunk_size() const
{
return m_length - m_index;
@@ -92,3 +105,8 @@ inline bool gprs_llc::fits_in_current_frame(uint8_t chunk_size) const
{
return m_length + chunk_size <= LLC_MAX_LEN;
}
+
+inline size_t gprs_llc_queue::size() const
+{
+ return this ? m_queue_size : 0;
+}
diff --git a/src/tbf.cpp b/src/tbf.cpp
index 8501b161..dc26cc70 100644
--- a/src/tbf.cpp
+++ b/src/tbf.cpp
@@ -219,7 +219,7 @@ void tbf_free(struct gprs_rlcmac_tbf *tbf)
tbf_name(tbf));
tbf->stop_timer();
#warning "TODO: Could/Should generate bssgp_tx_llc_discarded"
- tbf->m_llc.clear(tbf->bts);
+ tbf->llc_queue()->clear(tbf->bts);
tbf_unlink_pdch(tbf);
llist_del(&tbf->list.list);
@@ -451,6 +451,7 @@ static int setup_tbf(struct gprs_rlcmac_tbf *tbf, struct gprs_rlcmac_bts *bts,
gettimeofday(&tbf->meas.rssi_tv, NULL);
tbf->m_llc.init();
+ tbf->llc_queue()->init();
return 0;
}
diff --git a/src/tbf.h b/src/tbf.h
index d288669d..2a403c65 100644
--- a/src/tbf.h
+++ b/src/tbf.h
@@ -151,6 +151,8 @@ struct gprs_rlcmac_tbf {
void assign_imsi(const char *imsi);
uint8_t ta() const;
void set_ta(uint8_t);
+ gprs_llc_queue *llc_queue();
+ const gprs_llc_queue *llc_queue() const;
time_t created_ts() const;
@@ -229,6 +231,8 @@ protected:
/* Field to take the TA value if no MS is associated */
uint8_t m_ta;
+
+ gprs_llc_queue m_llc_queue;
private:
mutable char m_name_buf[60];
};
@@ -285,6 +289,16 @@ inline GprsMs *gprs_rlcmac_tbf::ms()
return m_ms;
}
+inline gprs_llc_queue *gprs_rlcmac_tbf::llc_queue()
+{
+ return &m_llc_queue;
+}
+
+inline const gprs_llc_queue *gprs_rlcmac_tbf::llc_queue() const
+{
+ return &m_llc_queue;
+}
+
inline bool gprs_rlcmac_tbf::is_tlli_valid() const
{
return tlli() != 0;
diff --git a/src/tbf_dl.cpp b/src/tbf_dl.cpp
index 2289e3f0..5b9c06ca 100644
--- a/src/tbf_dl.cpp
+++ b/src/tbf_dl.cpp
@@ -122,11 +122,11 @@ int gprs_rlcmac_dl_tbf::append_data(const uint8_t ms_class,
if (!llc_msg)
return -ENOMEM;
tv = (struct timeval *)msgb_put(llc_msg, sizeof(*tv));
- gprs_llc::calc_pdu_lifetime(bts, pdu_delay_csec, tv);
+ gprs_llc_queue::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);
- m_llc.enqueue(llc_msg);
+ llc_queue()->enqueue(llc_msg);
tbf_update_ms_class(this, ms_class);
start_llc_timer();
}
@@ -253,7 +253,7 @@ 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 = m_llc.dequeue())) {
+ while ((msg = llc_queue()->dequeue())) {
tv_disc = (struct timeval *)msg->data;
msgb_pull(msg, sizeof(*tv_disc));
tv_recv = (struct timeval *)msg->data;
@@ -262,11 +262,11 @@ struct msgb *gprs_rlcmac_dl_tbf::llc_dequeue(bssgp_bvc_ctx *bctx)
gprs_bssgp_update_queue_delay(tv_recv, &tv_now);
/* Is the age below the low water mark? */
- if (!gprs_llc::is_frame_expired(&tv_now2, tv_disc))
+ if (!gprs_llc_queue::is_frame_expired(&tv_now2, tv_disc))
break;
/* Is the age below the high water mark */
- if (!gprs_llc::is_frame_expired(&tv_now, tv_disc)) {
+ if (!gprs_llc_queue::is_frame_expired(&tv_now, tv_disc)) {
/* Has the previous message not been dropped? */
if (frames == 0)
break;
@@ -297,7 +297,7 @@ struct msgb *gprs_rlcmac_dl_tbf::llc_dequeue(bssgp_bvc_ctx *bctx)
LOGP(DRLCMACDL, LOGL_NOTICE, "%s Discarding LLC PDU "
"because lifetime limit reached, "
"count=%u new_queue_size=%zu\n",
- tbf_name(this), frames, m_llc.m_queue_size);
+ tbf_name(this), frames, llc_queue()->size());
if (frames > 0xff)
frames = 0xff;
if (octets > 0xffffff)
@@ -463,7 +463,7 @@ struct msgb *gprs_rlcmac_dl_tbf::create_new_bsn(const uint32_t fn, const uint8_t
break;
}
/* if FINAL chunk would fit precisely in space left */
- if (chunk == space && llist_empty(&m_llc.queue) && !keep_open(fn))
+ if (chunk == space && llc_queue()->size() == 0 && !keep_open(fn))
{
LOGP(DRLCMACDL, LOGL_DEBUG, "-- Chunk with length %d "
"would exactly fit into space (%d): because "
@@ -794,8 +794,8 @@ void gprs_rlcmac_dl_tbf::reuse_tbf(const uint8_t *data, const uint16_t len)
new_tbf->m_llc.put_frame(data, len);
bts->llc_frame_sched();
- while ((msg = m_llc.dequeue()))
- new_tbf->m_llc.enqueue(msg);
+ while ((msg = llc_queue()->dequeue()))
+ new_tbf->llc_queue()->enqueue(msg);
/* reset rlc states */
m_tx_counter = 0;
@@ -836,7 +836,7 @@ bool gprs_rlcmac_dl_tbf::need_control_ts() const
bool gprs_rlcmac_dl_tbf::have_data() const
{
- return m_llc.chunk_size() > 0 || !llist_empty(&m_llc.queue);
+ return m_llc.chunk_size() > 0 || llc_queue()->size() > 0;
}
int gprs_rlcmac_dl_tbf::frames_since_last_poll(unsigned fn) const