aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <holger@moiji-mobile.com>2013-11-13 16:56:15 +0100
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2013-11-13 17:08:07 +0100
commite23102602c94dc7fdd7cc6d383e7f6c576aa01ed (patch)
tree688e2172e335a6b1e1787e835a3d0339adee60a6 /src
parentb3d5ee2934f930e611cd4447b90dce6723340062 (diff)
llc: Move some more secrets from the TBF into the LLC
Introduce a method to append data to a TBF and then reset the read pointer when the frame has been sent.
Diffstat (limited to 'src')
-rw-r--r--src/llc.cpp12
-rw-r--r--src/llc.h31
-rw-r--r--src/tbf.cpp40
3 files changed, 57 insertions, 26 deletions
diff --git a/src/llc.cpp b/src/llc.cpp
index 1787daa6..3a50bc78 100644
--- a/src/llc.cpp
+++ b/src/llc.cpp
@@ -32,7 +32,7 @@ extern "C" {
void gprs_llc::reset()
{
index = 0;
- length = 0;
+ m_length = 0;
}
void gprs_llc::reset_frame_space()
@@ -48,11 +48,15 @@ void gprs_llc::enqueue(struct msgb *llc_msg)
void gprs_llc::put_frame(const uint8_t *data, size_t len)
{
/* only put frames when we are empty */
- OSMO_ASSERT(index == 0 && length == 0);
+ OSMO_ASSERT(index == 0 && m_length == 0);
+ append_frame(data, len);
+}
+void gprs_llc::append_frame(const uint8_t *data, size_t len)
+{
/* TODO: bounds check */
- memcpy(frame, data, len);
- length = len;
+ memcpy(frame + index, data, len);
+ m_length += len;
}
void gprs_llc::clear(BTS *bts)
diff --git a/src/llc.h b/src/llc.h
index d3b940ea..b22b1c20 100644
--- a/src/llc.h
+++ b/src/llc.h
@@ -37,20 +37,42 @@ struct gprs_llc {
struct msgb *dequeue();
void put_frame(const uint8_t *data, size_t 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;
+ uint16_t frame_length() const;
+
+ bool fits_in_current_frame(uint8_t size) const;
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 */
+ uint16_t m_length; /* len of current DL LLC_frame, 0 == no frame */
struct llist_head queue; /* queued LLC DL data */
};
inline uint16_t gprs_llc::chunk_size() const
{
- return length - index;
+ return m_length - index;
+}
+
+inline uint16_t gprs_llc::remaining_space() const
+{
+ return LLC_MAX_LEN - index;
+}
+
+inline uint16_t gprs_llc::frame_length() const
+{
+ return m_length;
+}
+
+inline void gprs_llc::consume(size_t len)
+{
+ index += len;
}
inline void gprs_llc::consume(uint8_t *data, size_t len)
@@ -59,3 +81,8 @@ inline void gprs_llc::consume(uint8_t *data, size_t len)
memcpy(data, frame + index, len);
index += len;
}
+
+inline bool gprs_llc::fits_in_current_frame(uint8_t chunk_size) const
+{
+ return index + chunk_size <= LLC_MAX_LEN;
+}
diff --git a/src/tbf.cpp b/src/tbf.cpp
index aa0f2236..41a94bcd 100644
--- a/src/tbf.cpp
+++ b/src/tbf.cpp
@@ -98,7 +98,6 @@ int gprs_rlcmac_tbf::append_data(const uint8_t ms_class,
LOGP(DRLCMAC, LOGL_DEBUG,
"%s in WAIT RELEASE state "
"(T3193), so reuse TBF\n", tbf_name(this));
-#warning "verify that m_llc.index/length is 0... check the state change"
bts->tbf_reused();
m_llc.put_frame(data, len);
bts->llc_frame_sched();
@@ -849,21 +848,21 @@ int gprs_rlcmac_tbf::assemble_forward_llc(uint8_t *data, uint8_t len)
/* data until next frame */
chunk = frame_offset[i + 1] - frame_offset[i];
}
- LOGP(DRLCMACUL, LOGL_DEBUG, "-- Appending chunk (len=%d) to "
- "frame at %d.\n", chunk, m_llc.index);
- if (m_llc.index + chunk > LLC_MAX_LEN) {
+ if (!m_llc.fits_in_current_frame(chunk)) {
LOGP(DRLCMACUL, LOGL_NOTICE, "%s LLC frame exceeds "
- "maximum size.\n", tbf_name(this));
- chunk = LLC_MAX_LEN - m_llc.index;
+ "maximum size %u.\n", tbf_name(this),
+ m_llc.remaining_space());
+ chunk = m_llc.remaining_space();
}
- memcpy(m_llc.frame + m_llc.index, data + frame_offset[i], chunk);
- m_llc.index += chunk;
+ m_llc.append_frame(data + frame_offset[i], chunk);
+ m_llc.consume(chunk);
/* not last frame. */
if (i != frames - 1) {
/* send frame to SGSN */
LOGP(DRLCMACUL, LOGL_INFO, "%s complete UL frame len=%d\n",
- tbf_name(this) , m_llc.index);
+ tbf_name(this) , m_llc.frame_length());
snd_ul_ud();
+ m_llc.reset();
/* also check if CV==0, because the frame may fill up the
* block precisely, then it is also complete. normally the
* frame would be extended into the next block with a 0-length
@@ -872,8 +871,9 @@ int gprs_rlcmac_tbf::assemble_forward_llc(uint8_t *data, uint8_t len)
/* send frame to SGSN */
LOGP(DRLCMACUL, LOGL_INFO, "%s complete UL frame "
"that fits precisely in last block: "
- "len=%d\n", tbf_name(this), m_llc.index);
+ "len=%d\n", tbf_name(this), m_llc.frame_length());
snd_ul_ud();
+ m_llc.reset();
}
}
@@ -1019,8 +1019,8 @@ do_resend:
"header, and we are done\n", chunk, space);
LOGP(DRLCMACDL, LOGL_INFO, "Complete DL frame for "
"%s that fits precisely in last block: "
- "len=%d\n", tbf_name(this), m_llc.length);
- gprs_rlcmac_dl_bw(this, m_llc.length);
+ "len=%d\n", tbf_name(this), m_llc.frame_length());
+ gprs_rlcmac_dl_bw(this, m_llc.frame_length());
/* block is filled, so there is no extension */
*e_pointer |= 0x01;
/* fill space */
@@ -1076,8 +1076,8 @@ do_resend:
data += chunk;
space -= chunk;
LOGP(DRLCMACDL, LOGL_INFO, "Complete DL frame for %s"
- "len=%d\n", tbf_name(this), m_llc.length);
- gprs_rlcmac_dl_bw(this, m_llc.length);
+ "len=%d\n", tbf_name(this), m_llc.frame_length());
+ gprs_rlcmac_dl_bw(this, m_llc.frame_length());
m_llc.reset();
/* dequeue next LLC frame, if any */
msg = llc_dequeue(gprs_bssgp_pcu_current_bctx());
@@ -1089,12 +1089,12 @@ do_resend:
msgb_free(msg);
}
/* if we have more data and we have space left */
- if (space > 0 && m_llc.length) {
+ if (space > 0 && m_llc.frame_length()) {
li->m = 1; /* we indicate more frames to follow */
continue;
}
/* if we don't have more LLC frames */
- if (!m_llc.length) {
+ if (!m_llc.frame_length()) {
LOGP(DRLCMACDL, LOGL_DEBUG, "-- Final block, so we "
"done.\n");
li->e = 1; /* we cannot extend */
@@ -1822,10 +1822,10 @@ int gprs_rlcmac_tbf::snd_ul_ud()
{
uint8_t qos_profile[3];
struct msgb *llc_pdu;
- unsigned msg_len = NS_HDR_LEN + BSSGP_HDR_LEN + m_llc.index;
+ unsigned msg_len = NS_HDR_LEN + BSSGP_HDR_LEN + m_llc.frame_length();
struct bssgp_bvc_ctx *bctx = gprs_bssgp_pcu_current_bctx();
- LOGP(DBSSGP, LOGL_INFO, "LLC [PCU -> SGSN] %s len=%d\n", tbf_name(this), m_llc.index);
+ LOGP(DBSSGP, LOGL_INFO, "LLC [PCU -> SGSN] %s len=%d\n", tbf_name(this), m_llc.frame_length());
if (!bctx) {
LOGP(DBSSGP, LOGL_ERROR, "No bctx\n");
m_llc.reset_frame_space();
@@ -1833,8 +1833,8 @@ int gprs_rlcmac_tbf::snd_ul_ud()
}
llc_pdu = msgb_alloc_headroom(msg_len, msg_len,"llc_pdu");
- uint8_t *buf = msgb_push(llc_pdu, TL16V_GROSS_LEN(sizeof(uint8_t)*m_llc.index));
- tl16v_put(buf, BSSGP_IE_LLC_PDU, sizeof(uint8_t)*m_llc.index, m_llc.frame);
+ uint8_t *buf = msgb_push(llc_pdu, TL16V_GROSS_LEN(sizeof(uint8_t)*m_llc.frame_length()));
+ tl16v_put(buf, BSSGP_IE_LLC_PDU, sizeof(uint8_t)*m_llc.frame_length(), m_llc.frame);
qos_profile[0] = QOS_PROFILE >> 16;
qos_profile[1] = QOS_PROFILE >> 8;
qos_profile[2] = QOS_PROFILE;