diff options
author | Holger Hans Peter Freyther <holger@moiji-mobile.com> | 2013-11-13 16:56:15 +0100 |
---|---|---|
committer | Holger Hans Peter Freyther <holger@moiji-mobile.com> | 2013-11-13 17:08:07 +0100 |
commit | e23102602c94dc7fdd7cc6d383e7f6c576aa01ed (patch) | |
tree | 688e2172e335a6b1e1787e835a3d0339adee60a6 /src | |
parent | b3d5ee2934f930e611cd4447b90dce6723340062 (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.cpp | 12 | ||||
-rw-r--r-- | src/llc.h | 31 | ||||
-rw-r--r-- | src/tbf.cpp | 40 |
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) @@ -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; |