[PATCH] osmo-pcu[master]: remove pcu own bitvector implementation

lynxis lazus gerrit-no-reply at lists.osmocom.org
Sat Feb 4 02:11:27 UTC 2017


Review at  https://gerrit.osmocom.org/1753

remove pcu own bitvector implementation

use osmocom bitvec which is exact the same, but use a pointer instead of
a reference.

Change-Id: Id8f797631d89aa12b6e48efb2dc153a3e2f059f7
---
M src/Makefile.am
D src/bitvector.cpp
D src/bitvector.h
M src/bts.cpp
A src/bts.cpp.orig
M src/csn1.cpp
M src/csn1.h
M src/egprs_rlc_compression.cpp
M src/encoding.cpp
M src/gprs_bssgp_pcu.cpp
M src/gprs_rlcmac.cpp
M src/gprs_rlcmac.h
M src/gsm_rlcmac.cpp
M src/pcu_main.cpp
M src/tbf.cpp
M src/tbf_ul.cpp
M tests/rlcmac/RLCMACTest.cpp
M tests/tbf/TbfTest.cpp
M tests/types/TypesTest.cpp
19 files changed, 2,222 insertions(+), 644 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/osmo-pcu refs/changes/53/1753/1

diff --git a/src/Makefile.am b/src/Makefile.am
index 7cc239b..97de06d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -46,7 +46,6 @@
 	gprs_ms.cpp \
 	gprs_ms_storage.cpp \
 	gsm_timer.cpp \
-	bitvector.cpp \
 	pcu_l1_if.cpp \
 	pcu_vty.c \
 	pcu_vty_functions.cpp \
@@ -80,7 +79,6 @@
 	gprs_ms_storage.h \
 	pcu_l1_if.h \
 	gsm_timer.h \
-	bitvector.h \
 	pcu_vty.h \
 	pcu_vty_functions.h \
 	tbf.h \
diff --git a/src/bitvector.cpp b/src/bitvector.cpp
deleted file mode 100644
index dcb3baf..0000000
--- a/src/bitvector.cpp
+++ /dev/null
@@ -1,120 +0,0 @@
-/* bitvector.cpp
- *
- * Copyright (C) 2012 Ivan Klyuchnikov
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-/*! \addtogroup bitvector
- *  @{
- */
-
-/*! \file bitvector.cpp
- *  \brief Additional functions for Osmocom bit vector abstraction.
- */
-
-#include <bitvector.h>
-extern "C" {
-#include <osmocom/core/talloc.h>
-}
-
-void *bv_tall_ctx;
-
-struct bitvec *bitvec_alloc(unsigned size)
-{
-	struct bitvec *bv = talloc_zero(bv_tall_ctx, struct bitvec);
-	bv->data_len = size;
-	bv->cur_bit = 0;
-	bv->data = talloc_zero_array(bv_tall_ctx, uint8_t, size);
-	return bv;
-}
-
-void bitvec_free(struct bitvec *bv)
-{
-	talloc_free(bv->data);
-	talloc_free(bv);
-}
-
-unsigned int bitvec_pack(struct bitvec *bv, uint8_t *buffer)
-{
-	unsigned int i = 0;
-	for (i = 0; i < bv->data_len; i++)
-	{
-		buffer[i] = bv->data[i];
-	}
-	return i;
-}
-
-unsigned int bitvec_unpack(struct bitvec *bv, uint8_t *buffer)
-{
-	unsigned int i = 0;
-	for (i = 0; i < bv->data_len; i++)
-	{
-		bv->data[i] = buffer[i];
-	}
-	return i;
-}
-
-
-int bitvec_unhex(struct bitvec *bv, const char* src)
-{
-	unsigned val;
-	unsigned write_index = 0;
-	unsigned digits = bv->data_len*2;
-	for (unsigned i=0; i<digits; i++) {
-		if (sscanf(src+i, "%1x", &val) < 1) {
-			return 1;
-		}
-		bitvec_write_field(bv, write_index,val, 4);
-	}
-	return 0;
-}
-
-uint64_t bitvec_read_field(struct bitvec *bv, unsigned& read_index, unsigned len)
-{
-	unsigned int i;
-	uint64_t ui = 0;
-	bv->cur_bit = read_index;
-
-	for (i = 0; i < len; i++) {
-		int bit = bitvec_get_bit_pos((const struct bitvec *)bv, bv->cur_bit);
-		if (bit < 0)
-			return bit;
-		if (bit)
-			ui |= ((uint64_t)1 << (len - i - 1));
-		bv->cur_bit++;
-	}
-	read_index += len;
-	return ui;
-}
-
-
-int bitvec_write_field_lh(struct bitvec *bv, unsigned& write_index,
-		uint64_t val, unsigned len)
-{
-	unsigned int i;
-	int rc;
-	bv->cur_bit = write_index;
-	for (i = 0; i < len; i++) {
-		bit_value bit = L;
-		if (val & ((uint64_t)1 << (len - i - 1)))
-			bit = H;
-		rc = bitvec_set_bit(bv, bit);
-		if (rc)
-			return rc;
-	}
-	write_index += len;
-	return 0;
-}
diff --git a/src/bitvector.h b/src/bitvector.h
deleted file mode 100644
index 246824d..0000000
--- a/src/bitvector.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* bitvector.h
- *
- * Copyright (C) 2012 Ivan Klyuchnikov
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#ifndef BITVECTOR_H
-#define BITVECTOR_H
-
-/*! \defgroup bitvector Bit vectors
- *  @{
- */
-
-/*! \file bitvector.h
- *  \brief Additional functions for Osmocom bit vector abstraction.
- */
-
-extern "C" {
-#include <osmocom/core/bitvec.h>
-}
-
-struct bitvec *bitvec_alloc(unsigned size);
-void bitvec_free(struct bitvec *bv);
-int bitvec_unhex(struct bitvec *bv, const char* src);
-unsigned int bitvec_pack(struct bitvec *bv, uint8_t *buffer);
-unsigned int bitvec_unpack(struct bitvec *bv, uint8_t *buffer);
-uint64_t bitvec_read_field(struct bitvec *bv, unsigned& read_index, unsigned len);
-int bitvec_write_field_lh(struct bitvec *bv, unsigned& write_index, uint64_t val, unsigned len);
-
-
-static inline int bitvec_write_field(struct bitvec *bv, unsigned& write_index, uint64_t val, unsigned len)
-{
-	/* Call the libosmocore variant */
-	return ::bitvec_write_field(bv, &write_index, val, len);
-}
-
-/*! }@ */
-
-#endif // BITVECTOR_H
diff --git a/src/bts.cpp b/src/bts.cpp
index 21e9d96..e857380 100644
--- a/src/bts.cpp
+++ b/src/bts.cpp
@@ -618,7 +618,7 @@
 			tsc = tbf->tsc();
 		}
 	}
-	bitvec *immediate_assignment = bitvec_alloc(22) /* without plen */;
+	bitvec *immediate_assignment = bitvec_alloc(22, tall_pcu_ctx) /* without plen */;
 	bitvec_unhex(immediate_assignment,
 		"2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
 
@@ -758,7 +758,7 @@
 	unsigned int ts = tbf->first_ts;
 
 	LOGP(DRLCMAC, LOGL_INFO, "TX: START %s Immediate Assignment Downlink (PCH)\n", tbf_name(tbf));
-	bitvec *immediate_assignment = bitvec_alloc(22); /* without plen */
+	bitvec *immediate_assignment = bitvec_alloc(22, tall_pcu_ctx); /* without plen */
 	bitvec_unhex(immediate_assignment, "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
 	/* use request reference that has maximum distance to current time,
 	 * so the assignment will not conflict with possible RACH requests. */
@@ -856,7 +856,7 @@
 		talloc_free(pag);
 		return NULL;
 	}
-	bitvec *pag_vec = bitvec_alloc(23);
+	bitvec *pag_vec = bitvec_alloc(23, tall_pcu_ctx);
 	if (!pag_vec) {
 		msgb_free(msg);
 		talloc_free(pag);
@@ -1577,7 +1577,7 @@
 		rc = rcv_data_block(data, fn, meas, cs);
 		break;
 	case GPRS_RLCMAC_CONTROL_BLOCK:
-		block = bitvec_alloc(len);
+		block = bitvec_alloc(len, tall_pcu_ctx);
 		if (!block)
 			return -ENOMEM;
 		bitvec_unpack(block, data);
diff --git a/src/bts.cpp.orig b/src/bts.cpp.orig
new file mode 100644
index 0000000..08ea05d
--- /dev/null
+++ b/src/bts.cpp.orig
@@ -0,0 +1,1748 @@
+/*
+ * Copyright (C) 2013 by Holger Hans Peter Freyther
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <bts.h>
+#include <poll_controller.h>
+#include <tbf.h>
+#include <encoding.h>
+#include <decoding.h>
+#include <rlc.h>
+#include <pcu_l1_if.h>
+
+#include <gprs_rlcmac.h>
+#include <gprs_debug.h>
+
+extern "C" {
+	#include <osmocom/core/talloc.h>
+	#include <osmocom/core/msgb.h>
+	#include <osmocom/core/stats.h>
+	#include <osmocom/gsm/protocol/gsm_04_08.h>
+}
+
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <string.h>
+
+extern void *tall_pcu_ctx;
+
+static BTS s_bts;
+
+/**
+ * For gcc-4.4 compat do not use extended initializer list but keep the
+ * order from the enum here. Once we support GCC4.7 and up we can change
+ * the code below.
+ */
+static const struct rate_ctr_desc bts_ctr_description[] = {
+	{ "tbf.dl.alloc",		"TBF DL Allocated     "},
+	{ "tbf.dl.freed",		"TBF DL Freed         "},
+	{ "tbf.dl.aborted",		"TBF DL Aborted       "},
+	{ "tbf.ul.alloc",		"TBF UL Allocated     "},
+	{ "tbf.ul.freed",		"TBF UL Freed         "},
+	{ "tbf.ul.aborted",		"TBF UL Aborted       "},
+	{ "tbf.reused",			"TBF Reused           "},
+	{ "tbf.alloc.algo-a",		"TBF Alloc Algo A     "},
+	{ "tbf.alloc.algo-b",		"TBF Alloc Algo B     "},
+	{ "tbf.failed.egprs-only",	"TBF Failed EGPRS-only"},
+	{ "rlc.sent",			"RLC Sent             "},
+	{ "rlc.resent",			"RLC Resent           "},
+	{ "rlc.restarted",		"RLC Restarted        "},
+	{ "rlc.stalled",		"RLC Stalled          "},
+	{ "rlc.nacked",			"RLC Nacked           "},
+	{ "rlc.final_block_resent",	"RLC Final Blk resent "},
+	{ "rlc.ass.timedout",		"RLC Assign Timeout   "},
+	{ "rlc.ass.failed",		"RLC Assign Failed    "},
+	{ "rlc.ack.timedout",		"RLC Ack Timeout      "},
+	{ "rlc.ack.failed",		"RLC Ack Failed       "},
+	{ "rlc.rel.timedout",		"RLC Release Timeout  "},
+	{ "rlc.late-block",		"RLC Late Block       "},
+	{ "rlc.sent-dummy",		"RLC Sent Dummy       "},
+	{ "rlc.sent-control",		"RLC Sent Control     "},
+	{ "rlc.dl_bytes",		"RLC DL Bytes         "},
+	{ "rlc.dl_payload_bytes",	"RLC DL Payload Bytes "},
+	{ "rlc.ul_bytes",		"RLC UL Bytes         "},
+	{ "rlc.ul_payload_bytes",	"RLC UL Payload Bytes "},
+	{ "decode.errors",		"Decode Errors        "},
+	{ "sba.allocated",		"SBA Allocated        "},
+	{ "sba.freed",			"SBA Freed            "},
+	{ "sba.timedout",		"SBA Timeout          "},
+	{ "llc.timeout",		"Timedout Frames      "},
+	{ "llc.dropped",		"Dropped Frames       "},
+	{ "llc.scheduled",		"Scheduled Frames     "},
+	{ "llc.dl_bytes",               "RLC encapsulated PDUs"},
+	{ "llc.ul_bytes",               "full PDUs received   "},
+	{ "rach.requests",		"RACH requests        "},
+	{ "11bit_rach.requests",	"11BIT_RACH requests  "},
+	{ "spb.uplink_first_segment",   "First seg of UL SPB  "},
+	{ "spb.uplink_second_segment",  "Second seg of UL SPB "},
+	{ "spb.downlink_first_segment", "First seg of DL SPB  "},
+	{ "spb.downlink_second_segment","Second seg of DL SPB "},
+	{ "immediate.assignment_UL",	"Immediate Assign UL  "},
+	{ "immediate.assignment_rej",   "Immediate Assign Rej "},
+	{ "immediate.assignment_DL",	"Immediate Assign DL  "},
+	{ "channel.request_description","Channel Request Desc "},
+	{ "pkt.ul_assignment",		"Packet UL Assignment "},
+	{ "pkt.access_reject",          "Packet Access Reject "},
+	{ "pkt.dl_assignment",		"Packet DL Assignment "},
+	{ "ul.control",			"UL control Block     "},
+	{ "ul.assignment_poll_timeout",	"UL Assign Timeout    "},
+	{ "ul.assignment_failed",	"UL Assign Failed     "},
+	{ "dl.assignment_timeout",	"DL Assign Timeout    "},
+	{ "dl.assignment_failed",	"DL Assign Failed     "},
+	{ "pkt.ul_ack_nack_timeout",	"PUAN Poll Timeout    "},
+	{ "pkt.ul_ack_nack_failed",	"PUAN poll Failed     "},
+	{ "pkt.dl_ack_nack_timeout",	"PDAN poll Timeout    "},
+	{ "pkt.dl_ack_nack_failed",	"PDAN poll Failed     "},
+	{ "gprs.downlink_cs1",		"CS1 downlink         "},
+	{ "gprs.downlink_cs2",		"CS2 downlink         "},
+	{ "gprs.downlink_cs3",		"CS3 downlink         "},
+	{ "gprs.downlink_cs4",		"CS4 downlink         "},
+	{ "egprs.downlink_mcs1",	"MCS1 downlink        "},
+	{ "egprs.downlink_mcs2",	"MCS2 downlink        "},
+	{ "egprs.downlink_mcs3",	"MCS3 downlink        "},
+	{ "egprs.downlink_mcs4",	"MCS4 downlink        "},
+	{ "egprs.downlink_mcs5",	"MCS5 downlink        "},
+	{ "egprs.downlink_mcs6",	"MCS6 downlink        "},
+	{ "egprs.downlink_mcs7",	"MCS7 downlink        "},
+	{ "egprs.downlink_mcs8",	"MCS8 downlink        "},
+	{ "egprs.downlink_mcs9",	"MCS9 downlink        "},
+	{ "gprs.uplink_cs1",		"CS1 Uplink           "},
+	{ "gprs.uplink_cs2",		"CS2 Uplink           "},
+	{ "gprs.uplink_cs3",		"CS3 Uplink           "},
+	{ "gprs.uplink_cs4",		"CS4 Uplink           "},
+	{ "egprs.uplink_mcs1",		"MCS1 Uplink          "},
+	{ "egprs.uplink_mcs2",		"MCS2 Uplink          "},
+	{ "egprs.uplink_mcs3",		"MCS3 Uplink          "},
+	{ "egprs.uplink_mcs4",		"MCS4 Uplink          "},
+	{ "egprs.uplink_mcs5",		"MCS5 Uplink          "},
+	{ "egprs.uplink_mcs6",		"MCS6 Uplink          "},
+	{ "egprs.uplink_mcs7",		"MCS7 Uplink          "},
+	{ "egprs.uplink_mcs8",		"MCS8 Uplink          "},
+	{ "egprs.uplink_mcs9",		"MCS9 Uplink          "},
+};
+
+static const struct rate_ctr_group_desc bts_ctrg_desc = {
+	"bts",
+	"BTS Statistics",
+	OSMO_STATS_CLASS_GLOBAL,
+	ARRAY_SIZE(bts_ctr_description),
+	bts_ctr_description,
+};
+
+static const struct osmo_stat_item_desc bts_stat_item_description[] = {
+	{ "ms.present",		"MS Present           ",
+		OSMO_STAT_ITEM_NO_UNIT, 4, 0},
+};
+
+static const struct osmo_stat_item_group_desc bts_statg_desc = {
+	"bts",
+	"BTS Statistics",
+	OSMO_STATS_CLASS_GLOBAL,
+	ARRAY_SIZE(bts_stat_item_description),
+	bts_stat_item_description,
+};
+
+BTS* BTS::main_bts()
+{
+	return &s_bts;
+}
+
+struct gprs_rlcmac_bts *BTS::bts_data()
+{
+	return &m_bts;
+}
+
+struct gprs_rlcmac_bts *bts_main_data()
+{
+	return BTS::main_bts()->bts_data();
+}
+
+struct rate_ctr_group *bts_main_data_stats()
+{
+	return BTS::main_bts()->rate_counters();
+}
+
+BTS::BTS()
+	: m_cur_fn(0)
+	, m_cur_blk_fn(-1)
+	, m_pollController(*this)
+	, m_sba(*this)
+	, m_ms_store(this)
+{
+	memset(&m_bts, 0, sizeof(m_bts));
+	m_bts.bts = this;
+
+	/* initialize back pointers */
+	for (size_t trx_no = 0; trx_no < ARRAY_SIZE(m_bts.trx); ++trx_no) {
+		struct gprs_rlcmac_trx *trx = &m_bts.trx[trx_no];
+		trx->trx_no = trx_no;
+		trx->bts = this;
+
+		for (size_t ts_no = 0; ts_no < ARRAY_SIZE(trx->pdch); ++ts_no) {
+			struct gprs_rlcmac_pdch *pdch = &trx->pdch[ts_no];
+			pdch->ts_no = ts_no;
+			pdch->trx = trx;
+		}
+	}
+
+	m_ratectrs = rate_ctr_group_alloc(tall_pcu_ctx, &bts_ctrg_desc, 0);
+	m_statg = osmo_stat_item_group_alloc(tall_pcu_ctx, &bts_statg_desc, 0);
+}
+
+BTS::~BTS()
+{
+	/* this can cause counter updates and must not be left to the
+	 * m_ms_store's destructor */
+	m_ms_store.cleanup();
+
+	rate_ctr_group_free(m_ratectrs);
+	osmo_stat_item_group_free(m_statg);
+}
+
+
+void BTS::set_current_frame_number(int fn)
+{
+	/* The UL frame numbers lag 3 behind the DL frames and the data
+	 * indication is only sent after all 4 frames of the block have been
+	 * received. Sometimes there is an idle frame between the end of one
+	 * and start of another frame (every 3 blocks).  So the timeout should
+	 * definitely be there if we're more than 8 frames past poll_fn. Let's
+	 * stay on the safe side and say 13 or more. An additional delay can
+	 * happen due to the block processing time in the DSP, so the delay of
+	 * decoded blocks relative to the timing clock can be much larger.
+	 * Values up to 50 frames have been observed under load. */
+	const static int max_delay = 60;
+
+	m_cur_fn = fn;
+	m_pollController.expireTimedout(m_cur_fn, max_delay);
+}
+
+void BTS::set_current_block_frame_number(int fn, unsigned max_delay)
+{
+	int delay = 0;
+	const int late_block_delay_thresh = 13;
+	const int fn_update_ok_min_delay = -500;
+	const int fn_update_ok_max_delay = 0;
+
+	/* frame numbers in the received blocks are assumed to be strongly
+	 * monotonic. */
+	if (m_cur_blk_fn >= 0) {
+		int delta = (fn + 2715648 * 3 / 2 - m_cur_blk_fn) % 2715648 - 2715648/2;
+		if (delta <= 0)
+			return;
+	}
+
+	/* Check block delay vs. the current frame number */
+	if (current_frame_number() != 0)
+		delay = (fn + 2715648 * 3 / 2 - current_frame_number()) % 2715648
+			- 2715648/2;
+	if (delay <= -late_block_delay_thresh) {
+		LOGP(DRLCMAC, LOGL_NOTICE,
+			"Late RLC block, FN delta: %d FN: %d curFN: %d\n",
+			delay, fn, current_frame_number());
+		rlc_late_block();
+	}
+
+	m_cur_blk_fn = fn;
+	if (delay < fn_update_ok_min_delay || delay > fn_update_ok_max_delay ||
+		current_frame_number() == 0)
+		m_cur_fn = fn;
+
+	m_pollController.expireTimedout(fn, max_delay);
+}
+
+int BTS::add_paging(uint8_t chan_needed, uint8_t *identity_lv)
+{
+	uint8_t l, trx, ts, any_tbf = 0;
+	struct gprs_rlcmac_tbf *tbf;
+	LListHead<gprs_rlcmac_tbf> *pos;
+	struct gprs_rlcmac_paging *pag;
+	uint8_t slot_mask[8];
+	int8_t first_ts; /* must be signed */
+
+	LListHead<gprs_rlcmac_tbf> *tbfs_lists[] = {
+		&m_ul_tbfs,
+		&m_dl_tbfs,
+		NULL
+	};
+
+
+	LOGP(DRLCMAC, LOGL_INFO, "Add RR paging: chan-needed=%d MI=%s\n",
+		chan_needed, osmo_hexdump(identity_lv + 1, identity_lv[0]));
+
+	/* collect slots to page
+	 * Mark slots for every TBF, but only mark one of it.
+	 * Mark only the first slot found.
+	 * Don't mark, if TBF uses a different slot that is already marked. */
+	memset(slot_mask, 0, sizeof(slot_mask));
+	for (l = 0; tbfs_lists[l]; l++) {
+		llist_for_each(pos, tbfs_lists[l]) {
+			tbf = pos->entry();
+			first_ts = -1;
+			for (ts = 0; ts < 8; ts++) {
+				if (tbf->pdch[ts]) {
+					/* remember the first slot found */
+					if (first_ts < 0)
+						first_ts = ts;
+					/* break, if we already marked a slot */
+					if ((slot_mask[tbf->trx->trx_no] & (1 << ts)))
+						break;
+				}
+			}
+			/* mark first slot found, if none is marked already */
+			if (ts == 8 && first_ts >= 0) {
+				LOGP(DRLCMAC, LOGL_DEBUG, "- %s uses "
+					"TRX=%d TS=%d, so we mark\n",
+					tbf_name(tbf),
+					tbf->trx->trx_no, first_ts);
+				slot_mask[tbf->trx->trx_no] |= (1 << first_ts);
+			} else
+				LOGP(DRLCMAC, LOGL_DEBUG, "- %s uses "
+					"already marked TRX=%d TS=%d\n",
+					tbf_name(tbf),
+					tbf->trx->trx_no, ts);
+		}
+	}
+
+	/* Now we have a list of marked slots. Every TBF uses at least one
+	 * of these slots. */
+
+	/* schedule paging to all marked slots */
+	for (trx = 0; trx < 8; trx++) {
+		if (slot_mask[trx] == 0)
+			continue;
+		for (ts = 0; ts < 8; ts++) {
+			if ((slot_mask[trx] & (1 << ts))) {
+				/* schedule */
+				pag = talloc_zero(tall_pcu_ctx,
+					struct gprs_rlcmac_paging);
+				if (!pag)
+					return -ENOMEM;
+				pag->chan_needed = chan_needed;
+				memcpy(pag->identity_lv, identity_lv,
+					identity_lv[0] + 1);
+				m_bts.trx[trx].pdch[ts].add_paging(pag);
+				LOGP(DRLCMAC, LOGL_INFO, "Paging on PACCH of "
+					"TRX=%d TS=%d\n", trx, ts);
+				any_tbf = 1;
+			}
+		}
+	}
+
+	if (!any_tbf)
+		LOGP(DRLCMAC, LOGL_INFO, "No paging, because no TBF\n");
+
+	return 0;
+}
+
+gprs_rlcmac_dl_tbf *BTS::dl_tbf_by_poll_fn(uint32_t fn, uint8_t trx, uint8_t ts)
+{
+	struct gprs_rlcmac_dl_tbf *tbf;
+	LListHead<gprs_rlcmac_tbf> *pos;
+
+	/* only one TBF can poll on specific TS/FN, because scheduler can only
+	 * schedule one downlink control block (with polling) at a FN per TS */
+	llist_for_each(pos, &m_dl_tbfs) {
+		tbf = as_dl_tbf(pos->entry());
+		if (tbf->state_is_not(GPRS_RLCMAC_RELEASING)
+		 && tbf->poll_state == GPRS_RLCMAC_POLL_SCHED
+		 && tbf->poll_fn == fn && tbf->trx->trx_no == trx
+		 && tbf->poll_ts == ts) {
+			return tbf;
+		}
+	}
+	return NULL;
+}
+gprs_rlcmac_ul_tbf *BTS::ul_tbf_by_poll_fn(uint32_t fn, uint8_t trx, uint8_t ts)
+{
+	struct gprs_rlcmac_ul_tbf *tbf;
+	LListHead<gprs_rlcmac_tbf> *pos;
+
+	/* only one TBF can poll on specific TS/FN, because scheduler can only
+	 * schedule one downlink control block (with polling) at a FN per TS */
+	llist_for_each(pos, &m_ul_tbfs) {
+		tbf = as_ul_tbf(pos->entry());
+		if (tbf->state_is_not(GPRS_RLCMAC_RELEASING)
+		 && tbf->poll_state == GPRS_RLCMAC_POLL_SCHED
+		 && tbf->poll_fn == fn && tbf->trx->trx_no == trx
+		 && tbf->poll_ts == ts) {
+			return tbf;
+		}
+	}
+	return NULL;
+}
+
+/* lookup downlink TBF Entity (by TFI) */
+gprs_rlcmac_dl_tbf *BTS::dl_tbf_by_tfi(uint8_t tfi, uint8_t trx, uint8_t ts)
+{
+	if (trx >= 8 || ts >= 8)
+		return NULL;
+
+	return m_bts.trx[trx].pdch[ts].dl_tbf_by_tfi(tfi);
+}
+
+/* lookup uplink TBF Entity (by TFI) */
+gprs_rlcmac_ul_tbf *BTS::ul_tbf_by_tfi(uint8_t tfi, uint8_t trx, uint8_t ts)
+{
+	if (trx >= 8 || ts >= 8)
+		return NULL;
+
+	return m_bts.trx[trx].pdch[ts].ul_tbf_by_tfi(tfi);
+}
+
+/*
+ * Search for free TFI and return TFI, TRX.
+ * This method returns the first TFI that is currently not used in any PDCH of
+ * a TRX. The first TRX that contains such an TFI is returned. Negative values
+ * indicate errors.
+ */
+int BTS::tfi_find_free(enum gprs_rlcmac_tbf_direction dir,
+		uint8_t *_trx, int8_t use_trx)
+{
+	struct gprs_rlcmac_pdch *pdch;
+	uint32_t free_tfis;
+	bool has_pdch = false;
+	uint8_t trx_from, trx_to, trx, ts, tfi;
+
+	if (use_trx >= 0 && use_trx < 8)
+		trx_from = trx_to = use_trx;
+	else {
+		trx_from = 0;
+		trx_to = 7;
+	}
+
+	/* find a TFI that is unused on all PDCH */
+	for (trx = trx_from; trx <= trx_to; trx++) {
+		bool trx_has_pdch = false;
+
+		free_tfis = 0xffffffff;
+
+		for (ts = 0; ts < 8; ts++) {
+			pdch = &m_bts.trx[trx].pdch[ts];
+			if (!pdch->is_enabled())
+				continue;
+			free_tfis &= ~pdch->assigned_tfi(dir);
+			trx_has_pdch = true;
+			has_pdch = true;
+		}
+		if (trx_has_pdch && free_tfis)
+			break;
+
+		free_tfis = 0;
+	}
+	if (!has_pdch) {
+		LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH available.\n");
+		return -EINVAL;
+	}
+
+	if (!free_tfis) {
+		LOGP(DRLCMAC, LOGL_NOTICE, "No TFI available.\n");
+		return -EBUSY;
+	}
+
+
+	LOGP(DRLCMAC, LOGL_DEBUG,
+		"Searching for first unallocated TFI: TRX=%d\n", trx);
+
+	/* find the first */
+	for (tfi = 0; tfi < 32; tfi++) {
+		if (free_tfis & 1 << tfi)
+			break;
+	}
+
+	OSMO_ASSERT(tfi < 32);
+
+	LOGP(DRLCMAC, LOGL_DEBUG, " Found TFI=%d.\n", tfi);
+	*_trx = trx;
+	return tfi;
+}
+
+int BTS::rcv_imm_ass_cnf(const uint8_t *data, uint32_t fn)
+{
+	struct gprs_rlcmac_dl_tbf *dl_tbf = NULL;
+	uint8_t plen;
+	uint32_t tlli;
+	GprsMs *ms;
+
+	/* move to IA Rest Octets */
+	plen = data[0] >> 2;
+	data += 1 + plen;
+
+	if ((*data & 0xf0) != 0xd0) {
+		LOGP(DRLCMAC, LOGL_ERROR, "Got IMM.ASS confirm, but rest "
+			"octets do not start with bit sequence 'HH01' "
+			"(Packet Downlink Assignment)\n");
+		return -EINVAL;
+	}
+
+	/* get TLLI from downlink assignment */
+	tlli = (*data++) << 28;
+	tlli |= (*data++) << 20;
+	tlli |= (*data++) << 12;
+	tlli |= (*data++) << 4;
+	tlli |= (*data++) >> 4;
+
+	ms = ms_by_tlli(tlli);
+	if (ms)
+		dl_tbf = ms->dl_tbf();
+	if (!dl_tbf) {
+		LOGP(DRLCMAC, LOGL_ERROR, "Got IMM.ASS confirm, but TLLI=%08x "
+			"does not exit\n", tlli);
+		return -EINVAL;
+	}
+
+	LOGP(DRLCMAC, LOGL_DEBUG, "Got IMM.ASS confirm for TLLI=%08x\n", tlli);
+
+	if (dl_tbf->m_wait_confirm)
+		tbf_timer_start(dl_tbf, 1, Tassign_agch);
+
+	return 0;
+}
+
+int BTS::rcv_imm_ass_cnf_dt(uint32_t tlli, uint32_t fn)
+{
+	GprsMs *ms;
+	struct gprs_rlcmac_dl_tbf *dl_tbf = NULL;
+
+	ms = ms_by_tlli(tlli);
+	if (ms)
+		dl_tbf = ms->dl_tbf();
+	if (!dl_tbf) {
+		LOGP(DRLCMAC, LOGL_ERROR, "Got IMM.ASS confirm, but TLLI=%08x "
+			"does not exit\n", tlli);
+		return -EINVAL;
+	}
+
+	LOGP(DRLCMAC, LOGL_DEBUG, "Got IMM.ASS confirm for TLLI=%08x\n", tlli);
+
+	if (dl_tbf->m_wait_confirm)
+		tbf_timer_start(dl_tbf, 1, Tassign_agch);
+
+	return 0;
+}
+
+int BTS::rcv_rach(uint16_t ra, uint32_t Fn, int16_t qta, uint8_t is_11bit,
+		enum ph_burst_type burst_type)
+{
+	struct gprs_rlcmac_ul_tbf *tbf = NULL;
+	uint8_t trx_no, ts_no = 0;
+	uint8_t sb = 0;
+	uint32_t sb_fn = 0;
+	int rc = 0;
+	int plen;
+	uint8_t usf = 7;
+	uint8_t tsc = 0, ta = qta2ta(qta);
+	uint16_t ms_class = 0;
+	uint16_t priority = 0;
+	bool failure = false;
+
+	rach_frame();
+
+	/* Santizize frame number */
+	Fn = Fn % 42432;
+
+	/* Restore the full frame number
+	 * (See also 3GPP TS 44.018, section 10.5.2.38) */
+	Fn = Fn + m_cur_fn - m_cur_fn % 42432;
+
+	if (is_11bit)
+		rach_frame_11bit();
+
+	LOGP(DRLCMAC, LOGL_DEBUG, "MS requests UL TBF on RACH, "
+		"so we provide one \n"
+		"ra=0x%02x Fn=%u qta=%d is_11bit=%d:\n", ra, Fn, qta, is_11bit);
+
+	sb = is_single_block(ra, burst_type, is_11bit, &ms_class, &priority);
+
+	if (sb) {
+		rc = sba()->alloc(&trx_no, &ts_no, &sb_fn, ta);
+		if (rc < 0) {
+			failure = true;
+			LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH resource for "
+					"single block allocation."
+					"sending Immediate "
+					"Assignment Uplink (AGCH) reject\n");
+		} else {
+			tsc = m_bts.trx[trx_no].pdch[ts_no].tsc;
+
+			LOGP(DRLCMAC, LOGL_DEBUG, "RX: [PCU <- BTS] RACH "
+				" qbit-ta=%d ra=0x%02x, Fn=%d (%d,%d,%d),"
+				" SBFn=%d\n",
+				qta, ra,
+				Fn, (Fn / (26 * 51)) % 32, Fn % 51, Fn % 26,
+				sb_fn);
+			LOGP(DRLCMAC, LOGL_INFO, "TX: Immediate Assignment "
+				"Uplink (AGCH)\n");
+		}
+	} else {
+		// Create new TBF
+		#warning "Copy and paste with other routines.."
+
+		if (is_11bit) {
+			tbf = tbf_alloc_ul_tbf(&m_bts, NULL, -1, 0,
+				ms_class, 1);
+		} else {
+			/* set class to 0, since we don't know the multislot
+			 * class yet */
+			tbf = tbf_alloc_ul_tbf(&m_bts, NULL, -1, 0, 0, 1);
+		}
+
+		if (!tbf) {
+			LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH resource sending "
+					"Immediate Assignment Uplink (AGCH) "
+					"reject\n");
+			rc = -EBUSY;
+			failure = true;
+		} else {
+			tbf->set_ta(ta);
+			tbf->set_state(GPRS_RLCMAC_FLOW);
+			tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_CCCH);
+			tbf_timer_start(tbf, 3169, m_bts.t3169, 0);
+			LOGP(DRLCMAC, LOGL_DEBUG, "%s [UPLINK] START\n",
+					tbf_name(tbf));
+			LOGP(DRLCMAC, LOGL_DEBUG, "%s RX: [PCU <- BTS] RACH "
+					"qbit-ta=%d ra=0x%02x, Fn=%d "
+					" (%d,%d,%d)\n",
+					tbf_name(tbf),
+					qta, ra, Fn, (Fn / (26 * 51)) % 32,
+					Fn % 51, Fn % 26);
+			LOGP(DRLCMAC, LOGL_INFO, "%s TX: START Immediate "
+					"Assignment Uplink (AGCH)\n",
+					tbf_name(tbf));
+			trx_no = tbf->trx->trx_no;
+			ts_no = tbf->first_ts;
+			usf = tbf->m_usf[ts_no];
+			tsc = tbf->tsc();
+		}
+	}
+	bitvec *immediate_assignment = bitvec_alloc(22) /* without plen */;
+	bitvec_unhex(immediate_assignment,
+		"2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
+
+
+	if (failure) {
+		plen = Encoding::write_immediate_assignment_reject(
+			immediate_assignment, ra, Fn,
+			burst_type);
+		immediate_assignment_reject();
+	}
+	else {
+		LOGP(DRLCMAC, LOGL_DEBUG,
+			" - TRX=%d (%d) TS=%d TA=%d TSC=%d TFI=%d USF=%d\n",
+			trx_no, m_bts.trx[trx_no].arfcn, ts_no, ta, tsc,
+			tbf ? tbf->tfi() : -1, usf);
+
+		plen = Encoding::write_immediate_assignment(
+			tbf, immediate_assignment, 0, ra, Fn, ta,
+			m_bts.trx[trx_no].arfcn, ts_no, tsc, usf, 0, sb_fn,
+			m_bts.alpha, m_bts.gamma, -1, burst_type, sb);
+	}
+
+	if (plen >= 0) {
+		immediate_assignment_ul_tbf();
+		pcu_l1if_tx_agch(immediate_assignment, plen);
+	}
+
+	bitvec_free(immediate_assignment);
+
+	return rc;
+}
+
+uint8_t BTS::is_single_block(uint16_t ra, enum ph_burst_type burst_type,
+		uint8_t is_11bit, uint16_t *ms_class, uint16_t *priority)
+{
+	uint8_t sb = 0, val = 0;
+
+	if (!is_11bit && (burst_type == GSM_L1_BURST_TYPE_ACCESS_0)) {
+
+		if ((ra & 0xf8) == 0x70) {
+			LOGP(DRLCMAC, LOGL_DEBUG, "MS requests single block "
+				"allocation\n");
+			sb = 1;
+		} else if (m_bts.force_two_phase) {
+			LOGP(DRLCMAC, LOGL_DEBUG, "MS requests single "
+				"phase access, but we force two phase "
+				"access\n");
+			sb = 1;
+		}
+
+	} else if (is_11bit &&
+		((burst_type == GSM_L1_BURST_TYPE_ACCESS_1) ||
+		(burst_type == GSM_L1_BURST_TYPE_ACCESS_2))) {
+
+		val = !!(ra & (1 << 10));
+
+		if (!val) {
+			if (m_bts.force_two_phase) {
+				LOGP(DRLCMAC, LOGL_DEBUG, "EGPRS 11 bit RACH "
+					"received. MS requests single phase "
+					"access but we force two phase "
+					"access\n");
+				sb = 1;
+			} else {
+				sb = 0;
+				*ms_class = (ra & 0x3e0) >> 5;
+				*priority = (ra & 0x18) >> 3;
+			}
+
+		} else {
+			LOGP(DRLCMAC, LOGL_DEBUG, "EGPRS 11 bit RACH received."
+				"MS requests single block allocation\n");
+			sb = 1;
+		}
+
+	} else if (is_11bit &&
+		(burst_type == GSM_L1_BURST_TYPE_ACCESS_0)) {
+		LOGP(DRLCMAC, LOGL_ERROR,
+			"Error: GPRS 11 bit RACH not supported\n");
+
+	} else if (burst_type == GSM_L1_BURST_TYPE_NONE) {
+		LOGP(DRLCMAC, LOGL_DEBUG, "pcu has not received burst type "
+			"from bts \n");
+
+		if ((ra & 0xf8) == 0x70) {
+			LOGP(DRLCMAC, LOGL_DEBUG, "MS requests single block "
+				"allocation\n");
+			sb = 1;
+		} else if (m_bts.force_two_phase) {
+			LOGP(DRLCMAC, LOGL_DEBUG, "MS requests single "
+				"phase access, but we force two phase "
+				"access\n");
+			sb = 1;
+		}
+	}
+
+	return sb;
+}
+
+/* depending on the current TBF, we assign on PACCH or AGCH */
+void BTS::trigger_dl_ass(
+	struct gprs_rlcmac_dl_tbf *dl_tbf,
+	struct gprs_rlcmac_tbf *old_tbf)
+{
+	/* stop pending timer */
+	dl_tbf->stop_timer();
+
+	/* check for downlink tbf:  */
+	if (old_tbf) {
+		LOGP(DRLCMAC, LOGL_DEBUG, "Send dowlink assignment on "
+			"PACCH, because %s exists\n", tbf_name(old_tbf));
+		old_tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_SEND_ASS;
+
+		old_tbf->was_releasing = old_tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE);
+
+		/* change state */
+		dl_tbf->set_state(GPRS_RLCMAC_ASSIGN);
+		if (!(dl_tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)))
+			dl_tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_PACCH);
+		/* start timer */
+		tbf_timer_start(dl_tbf, 0, Tassign_pacch);
+	} else {
+		uint32_t tlli = ntohl(dl_tbf->tlli());
+		LOGP(DRLCMAC, LOGL_DEBUG, "Send dowlink assignment for %s on PCH, no TBF exist (IMSI=%s)\n", tbf_name(dl_tbf), dl_tbf->imsi());
+		dl_tbf->was_releasing = dl_tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE);
+		/* change state */
+		dl_tbf->set_state(GPRS_RLCMAC_ASSIGN);
+		dl_tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_CCCH);
+		/* send immediate assignment */
+		/* FIXME TLLI != P-TMSI, but our sgsn use TLLI == P-TMSI */
+		gprs_rlcmac_paging_request((uint8_t *)&tlli, sizeof(dl_tbf->tlli()), dl_tbf->imsi());
+		dl_tbf->bts->snd_dl_ass(dl_tbf, 0, dl_tbf->imsi());
+		dl_tbf->m_wait_confirm = 1;
+		/* start timer */
+		tbf_timer_start(dl_tbf, 0, Tassign_pacch);
+
+	}
+}
+
+void BTS::snd_dl_ass(gprs_rlcmac_tbf *tbf, uint8_t poll, const char *imsi)
+{
+	int plen;
+	unsigned int ts = tbf->first_ts;
+
+	LOGP(DRLCMAC, LOGL_INFO, "TX: START %s Immediate Assignment Downlink (PCH)\n", tbf_name(tbf));
+	bitvec *immediate_assignment = bitvec_alloc(22); /* without plen */
+	bitvec_unhex(immediate_assignment, "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
+	/* use request reference that has maximum distance to current time,
+	 * so the assignment will not conflict with possible RACH requests. */
+	LOGP(DRLCMAC, LOGL_DEBUG, " - TRX=%d (%d) TS=%d TA=%d pollFN=%d\n",
+		tbf->trx->trx_no, tbf->trx->arfcn,
+		ts, tbf->ta(), poll ? tbf->poll_fn : -1);
+	plen = Encoding::write_immediate_assignment(tbf, immediate_assignment, 1, 125,
+		(tbf->pdch[ts]->last_rts_fn + 21216) % 2715648, tbf->ta(),
+		tbf->trx->arfcn, ts, tbf->tsc(), 7, poll,
+		tbf->poll_fn, m_bts.alpha, m_bts.gamma, -1);
+	if (plen >= 0) {
+		immediate_assignment_dl_tbf();
+		if (this->bts_data()->use_direct_tlli)
+			pcu_l1if_tx_agch_dt(tbf->tlli(), immediate_assignment, plen);
+		else
+			pcu_l1if_tx_agch(immediate_assignment, plen);
+	}
+
+	bitvec_free(immediate_assignment);
+}
+
+
+GprsMs *BTS::ms_alloc(uint8_t ms_class, uint8_t egprs_ms_class)
+{
+	GprsMs *ms;
+	ms = ms_store().create_ms();
+
+	ms->set_timeout(m_bts.ms_idle_sec);
+	ms->set_ms_class(ms_class);
+	ms->set_egprs_ms_class(egprs_ms_class);
+
+	return ms;
+}
+
+/*
+ * PDCH code below. TODO: move to a separate file
+ */
+
+void gprs_rlcmac_pdch::enable()
+{
+	/* TODO: Check if there are still allocated resources.. */
+	INIT_LLIST_HEAD(&paging_list);
+	m_is_enabled = 1;
+}
+
+void gprs_rlcmac_pdch::disable()
+{
+	/* TODO.. kick free_resources once we know the TRX/TS we are on */
+	m_is_enabled = 0;
+}
+
+void gprs_rlcmac_pdch::free_resources()
+{
+	struct gprs_rlcmac_paging *pag;
+
+	/* we are not enabled. there should be no resources */
+	if (!is_enabled())
+		return;
+
+	/* kick all TBF on slot */
+	gprs_rlcmac_tbf::free_all(this);
+
+	/* flush all pending paging messages */
+	while ((pag = dequeue_paging()))
+		talloc_free(pag);
+
+	trx->bts->sba()->free_resources(this);
+}
+
+struct gprs_rlcmac_paging *gprs_rlcmac_pdch::dequeue_paging()
+{
+	struct gprs_rlcmac_paging *pag;
+
+	if (llist_empty(&paging_list))
+		return NULL;
+	pag = llist_entry(paging_list.next, struct gprs_rlcmac_paging, list);
+	llist_del(&pag->list);
+
+	return pag;
+}
+
+struct msgb *gprs_rlcmac_pdch::packet_paging_request()
+{
+	struct gprs_rlcmac_paging *pag;
+	struct msgb *msg;
+	unsigned wp = 0, len;
+
+	/* no paging, no message */
+	pag = dequeue_paging();
+	if (!pag)
+		return NULL;
+
+	LOGP(DRLCMAC, LOGL_DEBUG, "Scheduling paging\n");
+
+	/* alloc message */
+	msg = msgb_alloc(23, "pag ctrl block");
+	if (!msg) {
+		talloc_free(pag);
+		return NULL;
+	}
+	bitvec *pag_vec = bitvec_alloc(23);
+	if (!pag_vec) {
+		msgb_free(msg);
+		talloc_free(pag);
+		return NULL;
+	}
+	wp = Encoding::write_packet_paging_request(pag_vec);
+
+	/* loop until message is full */
+	while (pag) {
+		/* try to add paging */
+		if ((pag->identity_lv[1] & 0x07) == 4) {
+			/* TMSI */
+			LOGP(DRLCMAC, LOGL_DEBUG, "- TMSI=0x%08x\n",
+				ntohl(*((uint32_t *)(pag->identity_lv + 1))));
+			len = 1 + 1 + 1 + 32 + 2 + 1;
+			if (pag->identity_lv[0] != 5) {
+				LOGP(DRLCMAC, LOGL_ERROR, "TMSI paging with "
+					"MI != 5 octets!\n");
+				goto continue_next;
+			}
+		} else {
+			/* MI */
+			LOGP(DRLCMAC, LOGL_DEBUG, "- MI=%s\n",
+				osmo_hexdump(pag->identity_lv + 1,
+					pag->identity_lv[0]));
+			len = 1 + 1 + 1 + 4 + (pag->identity_lv[0]<<3) + 2 + 1;
+			if (pag->identity_lv[0] > 8) {
+				LOGP(DRLCMAC, LOGL_ERROR, "Paging with "
+					"MI > 8 octets!\n");
+				goto continue_next;
+			}
+		}
+		if (wp + len > 184) {
+			LOGP(DRLCMAC, LOGL_DEBUG, "- Does not fit, so schedule "
+				"next time\n");
+			/* put back paging record, because does not fit */
+			llist_add_tail(&pag->list, &paging_list);
+			break;
+		}
+		Encoding::write_repeated_page_info(pag_vec, wp, pag->identity_lv[0],
+			pag->identity_lv + 1, pag->chan_needed);
+
+continue_next:
+		talloc_free(pag);
+		pag = dequeue_paging();
+	}
+
+	bitvec_pack(pag_vec, msgb_put(msg, 23));
+	RlcMacDownlink_t * mac_control_block = (RlcMacDownlink_t *)talloc_zero(tall_pcu_ctx, RlcMacDownlink_t);
+	LOGP(DRLCMAC, LOGL_DEBUG, "+++++++++++++++++++++++++ TX : Packet Paging Request +++++++++++++++++++++++++\n");
+	decode_gsm_rlcmac_downlink(pag_vec, mac_control_block);
+	LOGPC(DCSN1, LOGL_NOTICE, "\n");
+	LOGP(DRLCMAC, LOGL_DEBUG, "------------------------- TX : Packet Paging Request -------------------------\n");
+	bitvec_free(pag_vec);
+	talloc_free(mac_control_block);
+
+	return msg;
+}
+
+void gprs_rlcmac_pdch::add_paging(struct gprs_rlcmac_paging *pag)
+{
+	llist_add(&pag->list, &paging_list);
+}
+
+void gprs_rlcmac_pdch::rcv_control_ack(Packet_Control_Acknowledgement_t *packet, uint32_t fn)
+{
+	struct gprs_rlcmac_tbf *tbf, *new_tbf;
+	uint32_t tlli = 0;
+
+	tlli = packet->TLLI;
+	tbf = bts()->ul_tbf_by_poll_fn(fn, trx_no(), ts_no);
+	if (!tbf)
+		tbf = bts()->dl_tbf_by_poll_fn(fn, trx_no(), ts_no);
+
+	if (!tbf) {
+		LOGP(DRLCMAC, LOGL_NOTICE, "RX: [PCU <- BTS] PACKET CONTROL ACK with "
+			"unknown FN=%u TLLI=0x%08x (TRX %d TS %d)\n",
+			fn, tlli, trx_no(), ts_no);
+		return;
+	}
+	tbf->update_ms(tlli, GPRS_RLCMAC_UL_TBF);
+
+	LOGP(DRLCMAC, LOGL_DEBUG, "RX: [PCU <- BTS] %s Packet Control Ack\n", tbf_name(tbf));
+	tbf->poll_state = GPRS_RLCMAC_POLL_NONE;
+
+	/* check if this control ack belongs to packet uplink ack */
+	if (tbf->ul_ack_state == GPRS_RLCMAC_UL_ACK_WAIT_ACK) {
+		LOGP(DRLCMAC, LOGL_DEBUG, "TBF: [UPLINK] END %s\n", tbf_name(tbf));
+		tbf->ul_ack_state = GPRS_RLCMAC_UL_ACK_NONE;
+		if ((tbf->state_flags &
+			(1 << GPRS_RLCMAC_FLAG_TO_UL_ACK))) {
+			tbf->state_flags &=
+				~(1 << GPRS_RLCMAC_FLAG_TO_UL_ACK);
+				LOGP(DRLCMAC, LOGL_NOTICE, "Recovered uplink "
+					"ack for UL %s\n", tbf_name(tbf));
+		}
+		tbf_free(tbf);
+		return;
+	}
+	if (tbf->dl_ass_state == GPRS_RLCMAC_DL_ASS_WAIT_ACK) {
+		LOGP(DRLCMAC, LOGL_DEBUG, "TBF: [UPLINK] DOWNLINK ASSIGNED %s\n", tbf_name(tbf));
+		/* reset N3105 */
+		tbf->n3105 = 0;
+		tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_NONE;
+
+		new_tbf = tbf->ms() ? tbf->ms()->dl_tbf() : NULL;
+		if (!new_tbf) {
+			LOGP(DRLCMAC, LOGL_ERROR, "Got ACK, but DL "
+				"TBF is gone TLLI=0x%08x\n", tlli);
+			return;
+		}
+		if (tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE) &&
+				tbf->direction == new_tbf->direction)
+			tbf_free(tbf);
+
+		if ((new_tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH))) {
+			/* We now know that the PACCH really existed */
+			LOGP(DRLCMAC, LOGL_INFO,
+				"The TBF has been confirmed on the PACCH, "
+				"changed type from CCCH to PACCH for %s\n",
+				tbf_name(new_tbf));
+			new_tbf->state_flags &= ~(1 << GPRS_RLCMAC_FLAG_CCCH);
+			new_tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_PACCH);
+		}
+		new_tbf->set_state(GPRS_RLCMAC_FLOW);
+		/* stop pending assignment timer */
+		new_tbf->stop_timer();
+		if ((new_tbf->state_flags &
+			(1 << GPRS_RLCMAC_FLAG_TO_DL_ASS))) {
+			new_tbf->state_flags &=
+				~(1 << GPRS_RLCMAC_FLAG_TO_DL_ASS);
+			LOGP(DRLCMAC, LOGL_NOTICE, "Recovered downlink "
+				"assignment for %s\n", tbf_name(new_tbf));
+		}
+		tbf_assign_control_ts(new_tbf);
+		return;
+	}
+	if (tbf->ul_ass_state == GPRS_RLCMAC_UL_ASS_WAIT_ACK) {
+		LOGP(DRLCMAC, LOGL_DEBUG, "TBF: [DOWNLINK] UPLINK ASSIGNED %s\n", tbf_name(tbf));
+		/* reset N3105 */
+		tbf->n3105 = 0;
+		tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_NONE;
+
+		new_tbf = tbf->ms() ? tbf->ms()->ul_tbf() : NULL;
+		if (!new_tbf) {
+			LOGP(DRLCMAC, LOGL_ERROR, "Got ACK, but UL "
+				"TBF is gone TLLI=0x%08x\n", tlli);
+			return;
+		}
+		if (tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE) &&
+				tbf->direction == new_tbf->direction)
+			tbf_free(tbf);
+
+		new_tbf->set_state(GPRS_RLCMAC_FLOW);
+		if ((new_tbf->state_flags &
+			(1 << GPRS_RLCMAC_FLAG_TO_UL_ASS))) {
+			new_tbf->state_flags &=
+				~(1 << GPRS_RLCMAC_FLAG_TO_UL_ASS);
+			LOGP(DRLCMAC, LOGL_NOTICE, "Recovered uplink "
+				"assignment for UL %s\n", tbf_name(new_tbf));
+		}
+		tbf_assign_control_ts(new_tbf);
+		/* there might be LLC packets waiting in the queue, but the DL
+		 * TBF might have been released while the UL TBF has been
+		 * established */
+		if (new_tbf->ms()->need_dl_tbf())
+			new_tbf->establish_dl_tbf_on_pacch();
+
+		return;
+	}
+	LOGP(DRLCMAC, LOGL_ERROR, "Error: received PACET CONTROL ACK "
+		"at no request\n");
+}
+
+static void get_rx_qual_meas(struct pcu_l1_meas *meas, uint8_t rx_qual_enc)
+{
+	static const int16_t rx_qual_map[] = {
+		0, /* 0,14 % */
+		0, /* 0,28 % */
+		1, /* 0,57 % */
+		1, /* 1,13 % */
+		2, /* 2,26 % */
+		5, /* 4,53 % */
+		9, /* 9,05 % */
+		18, /* 18,10 % */
+	};
+
+	meas->set_ms_rx_qual(rx_qual_map[
+		OSMO_MIN(rx_qual_enc, ARRAY_SIZE(rx_qual_map)-1)
+		]);
+}
+
+static void get_meas(struct pcu_l1_meas *meas,
+	const Packet_Resource_Request_t *qr)
+{
+	unsigned i;
+
+	meas->set_ms_c_value(qr->C_VALUE);
+	if (qr->Exist_SIGN_VAR)
+		meas->set_ms_sign_var((qr->SIGN_VAR + 2) / 4); /* SIGN_VAR * 0.25 dB */
+
+	for (i = 0; i < OSMO_MIN(ARRAY_SIZE(qr->Slot), ARRAY_SIZE(meas->ts)); i++)
+	{
+		if (qr->Slot[i].Exist) {
+			LOGP(DRLCMAC, LOGL_INFO,
+				"Packet resource request: i_level[%d] = %d\n",
+				i, qr->Slot[i].I_LEVEL);
+			meas->set_ms_i_level(i, -2 * qr->Slot[i].I_LEVEL);
+		}
+	}
+}
+
+static void get_meas(struct pcu_l1_meas *meas,
+	const Channel_Quality_Report_t *qr)
+{
+	unsigned i;
+
+	get_rx_qual_meas(meas, qr->RXQUAL);
+	meas->set_ms_c_value(qr->C_VALUE);
+	meas->set_ms_sign_var((qr->SIGN_VAR + 2) / 4); /* SIGN_VAR * 0.25 dB */
+
+	for (i = 0; i < OSMO_MIN(ARRAY_SIZE(qr->Slot), ARRAY_SIZE(meas->ts)); i++)
+	{
+		if (qr->Slot[i].Exist) {
+			LOGP(DRLCMAC, LOGL_INFO,
+				"Channel quality report: i_level[%d] = %d\n",
+				i, qr->Slot[i].I_LEVEL_TN);
+			meas->set_ms_i_level(i, -2 * qr->Slot[i].I_LEVEL_TN);
+		}
+	}
+}
+
+void gprs_rlcmac_pdch::rcv_control_dl_ack_nack(Packet_Downlink_Ack_Nack_t *ack_nack, uint32_t fn)
+{
+	int8_t tfi = 0; /* must be signed */
+	struct gprs_rlcmac_dl_tbf *tbf;
+	int rc;
+	struct pcu_l1_meas meas;
+	int num_blocks;
+	uint8_t bits_data[RLC_GPRS_WS/8];
+	bitvec bits;
+	int bsn_begin, bsn_end;
+	char show_bits[RLC_GPRS_WS + 1];
+
+	tfi = ack_nack->DOWNLINK_TFI;
+	tbf = bts()->dl_tbf_by_poll_fn(fn, trx_no(), ts_no);
+	if (!tbf) {
+		LOGP(DRLCMAC, LOGL_NOTICE, "RX: [PCU <- BTS] PACKET DOWNLINK ACK with "
+			"unknown FN=%u TFI=%d (TRX %d TS %d)\n",
+			fn, tfi, trx_no(), ts_no);
+		return;
+	}
+	if (tbf->tfi() != tfi) {
+		LOGP(DRLCMAC, LOGL_NOTICE, "RX: [PCU <- BTS] PACKET DOWNLINK ACK with "
+			"wrong TFI=%d, ignoring!\n", tfi);
+		return;
+	}
+	tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_DL_ACK);
+	if ((tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_TO_DL_ACK))) {
+		tbf->state_flags &= ~(1 << GPRS_RLCMAC_FLAG_TO_DL_ACK);
+		LOGP(DRLCMAC, LOGL_NOTICE, "Recovered downlink ack "
+			"for %s\n", tbf_name(tbf));
+	}
+	/* reset N3105 */
+	tbf->n3105 = 0;
+	tbf->stop_t3191();
+	LOGP(DRLCMAC, LOGL_DEBUG, "RX: [PCU <- BTS] %s Packet Downlink Ack/Nack\n", tbf_name(tbf));
+	tbf->poll_state = GPRS_RLCMAC_POLL_NONE;
+
+	bits.data = bits_data;
+	bits.data_len = sizeof(bits_data);
+	bits.cur_bit = 0;
+
+	num_blocks = Decoding::decode_gprs_acknack_bits(
+		&ack_nack->Ack_Nack_Description, &bits,
+		&bsn_begin, &bsn_end, &tbf->m_window);
+
+	LOGP(DRLCMAC, LOGL_DEBUG,
+		"Got GPRS DL ACK bitmap: SSN: %d, BSN %d to %d - 1 (%d blocks), "
+		"\"%s\"\n",
+		ack_nack->Ack_Nack_Description.STARTING_SEQUENCE_NUMBER,
+		bsn_begin, bsn_end, num_blocks,
+		(Decoding::extract_rbb(&bits, show_bits), show_bits));
+
+	rc = tbf->rcvd_dl_ack(
+		ack_nack->Ack_Nack_Description.FINAL_ACK_INDICATION,
+		bsn_begin, &bits);
+	if (rc == 1) {
+		tbf_free(tbf);
+		return;
+	}
+	/* check for channel request */
+	if (ack_nack->Exist_Channel_Request_Description) {
+
+		bts()->channel_request_description();
+
+		/* This call will register the new TBF with the MS on success */
+		gprs_rlcmac_ul_tbf *ul_tbf = tbf_alloc_ul(bts_data(),
+			tbf->trx->trx_no,
+			tbf->ms_class(), tbf->ms()->egprs_ms_class(),
+			tbf->tlli(), tbf->ta(), tbf->ms());
+
+		/* schedule uplink assignment or reject*/
+		if (ul_tbf) {
+			LOGP(DRLCMAC, LOGL_DEBUG, "MS requests UL TBF in ack "
+				"message, so we provide one:\n");
+			tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_SEND_ASS;
+		} else {
+			LOGP(DRLCMAC, LOGL_DEBUG, "MS requests UL TBF in ack "
+				"message, so we pacekt access reject:\n");
+			tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_SEND_ASS_REJ;
+		}
+	}
+	/* get measurements */
+	if (tbf->ms()) {
+		get_meas(&meas, &ack_nack->Channel_Quality_Report);
+		tbf->ms()->update_l1_meas(&meas);
+	}
+}
+
+void gprs_rlcmac_pdch::rcv_control_egprs_dl_ack_nack(EGPRS_PD_AckNack_t *ack_nack, uint32_t fn)
+{
+	int8_t tfi = 0; /* must be signed */
+	struct gprs_rlcmac_dl_tbf *tbf;
+	struct pcu_l1_meas meas;
+	int rc;
+	int num_blocks;
+	uint8_t bits_data[RLC_EGPRS_MAX_WS/8];
+	char show_bits[RLC_EGPRS_MAX_WS + 1];
+	bitvec bits;
+	int bsn_begin, bsn_end;
+
+	tfi = ack_nack->DOWNLINK_TFI;
+	tbf = bts()->dl_tbf_by_poll_fn(fn, trx_no(), ts_no);
+	if (!tbf) {
+		LOGP(DRLCMAC, LOGL_NOTICE, "EGPRS PACKET DOWNLINK ACK with "
+			"unknown FN=%u TFI=%d (TRX %d TS %d)\n",
+			fn, tfi, trx_no(), ts_no);
+		return;
+	}
+	if (tbf->tfi() != tfi) {
+		LOGP(DRLCMAC, LOGL_NOTICE, "EGPRS PACKET DOWNLINK ACK with "
+			"wrong TFI=%d, ignoring!\n", tfi);
+		return;
+	}
+	tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_DL_ACK);
+	if ((tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_TO_DL_ACK))) {
+		tbf->state_flags &= ~(1 << GPRS_RLCMAC_FLAG_TO_DL_ACK);
+		LOGP(DRLCMAC, LOGL_NOTICE, "Recovered EGPRS downlink ack "
+			"for %s\n", tbf_name(tbf));
+	}
+	/* reset N3105 */
+	tbf->n3105 = 0;
+	tbf->stop_t3191();
+	LOGP(DRLCMAC, LOGL_DEBUG,
+		"RX: [PCU <- BTS] %s EGPRS Packet Downlink Ack/Nack\n",
+		tbf_name(tbf));
+	tbf->poll_state = GPRS_RLCMAC_POLL_NONE;
+
+	LOGP(DRLCMAC, LOGL_DEBUG, "EGPRS ACK/NACK: "
+		"ut: %d, final: %d, bow: %d, eow: %d, ssn: %d, have_crbb: %d, "
+		"urbb_len:%d, %p, %p, %d, %d, win: %d-%d, urbb: %s\n",
+		(int)ack_nack->EGPRS_AckNack.UnionType,
+		(int)ack_nack->EGPRS_AckNack.Desc.FINAL_ACK_INDICATION,
+		(int)ack_nack->EGPRS_AckNack.Desc.BEGINNING_OF_WINDOW,
+		(int)ack_nack->EGPRS_AckNack.Desc.END_OF_WINDOW,
+		(int)ack_nack->EGPRS_AckNack.Desc.STARTING_SEQUENCE_NUMBER,
+		(int)ack_nack->EGPRS_AckNack.Desc.Exist_CRBB,
+		(int)ack_nack->EGPRS_AckNack.Desc.URBB_LENGTH,
+		(void *)&ack_nack->EGPRS_AckNack.UnionType,
+		(void *)&ack_nack->EGPRS_AckNack.Desc,
+		(int)offsetof(EGPRS_AckNack_t, Desc),
+		(int)offsetof(EGPRS_AckNack_w_len_t, Desc),
+		tbf->m_window.v_a(),
+		tbf->m_window.v_s(),
+		osmo_hexdump((const uint8_t *)&ack_nack->EGPRS_AckNack.Desc.URBB,
+			sizeof(ack_nack->EGPRS_AckNack.Desc.URBB)));
+
+	bits.data = bits_data;
+	bits.data_len = sizeof(bits_data);
+	bits.cur_bit = 0;
+
+	num_blocks = Decoding::decode_egprs_acknack_bits(
+		&ack_nack->EGPRS_AckNack.Desc, &bits,
+		&bsn_begin, &bsn_end, &tbf->m_window);
+
+	LOGP(DRLCMAC, LOGL_DEBUG,
+		"Got EGPRS DL ACK bitmap: SSN: %d, BSN %d to %d - 1 (%d blocks), "
+		"\"%s\"\n",
+		ack_nack->EGPRS_AckNack.Desc.STARTING_SEQUENCE_NUMBER,
+		bsn_begin, bsn_end, num_blocks,
+		(Decoding::extract_rbb(&bits, show_bits), show_bits)
+	    );
+
+	rc = tbf->rcvd_dl_ack(
+		ack_nack->EGPRS_AckNack.Desc.FINAL_ACK_INDICATION,
+		bsn_begin, &bits);
+	if (rc == 1) {
+		tbf_free(tbf);
+		return;
+	}
+
+	/* check for channel request */
+	if (ack_nack->Exist_ChannelRequestDescription) {
+
+		bts()->channel_request_description();
+
+		/* This call will register the new TBF with the MS on success */
+		gprs_rlcmac_ul_tbf *ul_tbf = tbf_alloc_ul(bts_data(),
+			tbf->trx->trx_no,
+			tbf->ms_class(), tbf->ms()->egprs_ms_class(),
+			tbf->tlli(), tbf->ta(), tbf->ms());
+
+		/* schedule uplink assignment or reject*/
+		if (ul_tbf) {
+			LOGP(DRLCMAC, LOGL_DEBUG, "MS requests UL TBF in ack "
+				"message, so we provide one:\n");
+			tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_SEND_ASS;
+		} else {
+			LOGP(DRLCMAC, LOGL_DEBUG, "MS requests UL TBF in ack "
+				"message, so we send packet access reject:\n");
+			tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_SEND_ASS_REJ;
+		}
+	}
+
+	/* get measurements */
+	if (tbf->ms()) {
+		/* TODO: Implement Measurements parsing for EGPRS */
+		/*
+		get_meas(&meas, &ack_nack->Channel_Quality_Report);
+		tbf->ms()->update_l1_meas(&meas);
+		*/
+	}
+}
+
+void gprs_rlcmac_pdch::rcv_resource_request(Packet_Resource_Request_t *request, uint32_t fn)
+{
+	struct gprs_rlcmac_sba *sba;
+
+	if (request->ID.UnionType) {
+		struct gprs_rlcmac_ul_tbf *ul_tbf = NULL;
+		struct gprs_rlcmac_dl_tbf *dl_tbf = NULL;
+		uint32_t tlli = request->ID.u.TLLI;
+		uint8_t ms_class = 0;
+		uint8_t egprs_ms_class = 0;
+		uint8_t ta = GSM48_TA_INVALID;
+		struct pcu_l1_meas meas;
+
+		GprsMs *ms = bts()->ms_by_tlli(tlli);
+		/* Keep the ms, even if it gets idle temporarily */
+		GprsMs::Guard guard(ms);
+
+		if (ms) {
+			ul_tbf = ms->ul_tbf();
+			dl_tbf = ms->dl_tbf();
+			ta = ms->ta();
+		}
+
+		LOGP(DRLCMAC, LOGL_DEBUG, "RX: [PCU <- BTS] Resource Request over PDCH\n");
+
+		/* We got a RACH so the MS was in packet idle mode and thus
+		 * didn't have any active TBFs */
+		if (ul_tbf) {
+			LOGP(DRLCMACUL, LOGL_NOTICE, "Got RACH from "
+				"TLLI=0x%08x while %s still "
+				"exists. Killing pending UL TBF\n",
+				tlli, tbf_name(ul_tbf));
+			tbf_free(ul_tbf);
+			ul_tbf = NULL;
+		}
+
+		if (dl_tbf) {
+			LOGP(DRLCMACUL, LOGL_NOTICE, "Got RACH from "
+				"TLLI=0x%08x while %s still exists. "
+				"Release pending DL TBF\n", tlli,
+				tbf_name(dl_tbf));
+			tbf_free(dl_tbf);
+			dl_tbf = NULL;
+		}
+		LOGP(DRLCMAC, LOGL_DEBUG, "RX: [PCU <- BTS] MS requests UL TBF "
+			"in packet resource request of single "
+			"block, so we provide one:\n");
+		sba = bts()->sba()->find(this, fn);
+		if (!sba) {
+			LOGP(DRLCMAC, LOGL_NOTICE, "MS requests UL TBF "
+				"in packet resource request of single "
+				"block, but there is no resource request "
+				"scheduled!\n");
+		} else {
+			ta = sba->ta;
+			bts()->sba()->free_sba(sba);
+		}
+		if (request->Exist_MS_Radio_Access_capability) {
+			ms_class = Decoding::get_ms_class_by_capability(
+				&request->MS_Radio_Access_capability);
+			egprs_ms_class =
+				Decoding::get_egprs_ms_class_by_capability(
+					&request->MS_Radio_Access_capability);
+		}
+		if (!ms_class)
+			LOGP(DRLCMAC, LOGL_NOTICE, "MS does not give us a class.\n");
+		if (egprs_ms_class)
+			LOGP(DRLCMAC, LOGL_NOTICE,
+				"MS supports EGPRS multislot class %d.\n",
+				egprs_ms_class);
+		ul_tbf = tbf_alloc_ul(bts_data(), trx_no(), ms_class,
+			egprs_ms_class, tlli, ta, ms);
+		if (!ul_tbf)
+			return;
+
+		/* set control ts to current MS's TS, until assignment complete */
+		LOGP(DRLCMAC, LOGL_DEBUG, "Change control TS to %d until assinment is complete.\n", ts_no);
+		ul_tbf->control_ts = ts_no;
+		/* schedule uplink assignment */
+		ul_tbf->ul_ass_state = GPRS_RLCMAC_UL_ASS_SEND_ASS;
+
+		/* get capabilities */
+		if (ul_tbf->ms())
+			ul_tbf->ms()->set_egprs_ms_class(egprs_ms_class);
+
+		/* get measurements */
+		if (ul_tbf->ms()) {
+			get_meas(&meas, request);
+			ul_tbf->ms()->update_l1_meas(&meas);
+		}
+		return;
+	}
+
+	if (request->ID.u.Global_TFI.UnionType) {
+		struct gprs_rlcmac_dl_tbf *dl_tbf;
+		int8_t tfi = request->ID.u.Global_TFI.u.DOWNLINK_TFI;
+		dl_tbf = bts()->dl_tbf_by_tfi(tfi, trx_no(), ts_no);
+		if (!dl_tbf) {
+			LOGP(DRLCMAC, LOGL_NOTICE, "PACKET RESSOURCE REQ unknown downlink TFI=%d\n", tfi);
+			return;
+		}
+		LOGP(DRLCMAC, LOGL_ERROR,
+			"RX: [PCU <- BTS] %s FIXME: Packet resource request\n",
+			tbf_name(dl_tbf));
+	} else {
+		struct gprs_rlcmac_ul_tbf *ul_tbf;
+		int8_t tfi = request->ID.u.Global_TFI.u.UPLINK_TFI;
+		ul_tbf = bts()->ul_tbf_by_tfi(tfi, trx_no(), ts_no);
+		if (!ul_tbf) {
+			LOGP(DRLCMAC, LOGL_NOTICE, "PACKET RESSOURCE REQ unknown uplink TFI=%d\n", tfi);
+			return;
+		}
+		LOGP(DRLCMAC, LOGL_ERROR,
+			"RX: [PCU <- BTS] %s FIXME: Packet resource request\n",
+			tbf_name(ul_tbf));
+	}
+}
+
+void gprs_rlcmac_pdch::rcv_measurement_report(Packet_Measurement_Report_t *report, uint32_t fn)
+{
+	struct gprs_rlcmac_sba *sba;
+
+	LOGP(DRLCMAC, LOGL_DEBUG, "RX: [PCU <- BTS] Measurement Report\n");
+	sba = bts()->sba()->find(this, fn);
+	if (!sba) {
+		LOGP(DRLCMAC, LOGL_NOTICE, "MS send measurement "
+			"in packet resource request of single "
+			"block, but there is no resource request "
+			"scheduled! TLLI=0x%08x\n", report->TLLI);
+	} else {
+		GprsMs *ms = bts()->ms_store().get_ms(report->TLLI);
+		if (!ms)
+			LOGP(DRLCMAC, LOGL_NOTICE, "MS send measurement "
+				"but TLLI 0x%08x is unknown\n", report->TLLI);
+		else
+			ms->set_ta(sba->ta);
+
+		bts()->sba()->free_sba(sba);
+	}
+	gprs_rlcmac_meas_rep(report);
+}
+
+/* Received Uplink RLC control block. */
+int gprs_rlcmac_pdch::rcv_control_block(
+	bitvec *rlc_block, uint32_t fn)
+{
+	RlcMacUplink_t * ul_control_block = (RlcMacUplink_t *)talloc_zero(tall_pcu_ctx, RlcMacUplink_t);
+	LOGP(DRLCMAC, LOGL_DEBUG, "+++++++++++++++++++++++++ RX : Uplink Control Block +++++++++++++++++++++++++\n");
+	decode_gsm_rlcmac_uplink(rlc_block, ul_control_block);
+	LOGPC(DCSN1, LOGL_NOTICE, "\n");
+	LOGP(DRLCMAC, LOGL_DEBUG, "------------------------- RX : Uplink Control Block -------------------------\n");
+	bts()->rlc_rcvd_control();
+	switch (ul_control_block->u.MESSAGE_TYPE) {
+	case MT_PACKET_CONTROL_ACK:
+		rcv_control_ack(&ul_control_block->u.Packet_Control_Acknowledgement, fn);
+		break;
+	case MT_PACKET_DOWNLINK_ACK_NACK:
+		rcv_control_dl_ack_nack(&ul_control_block->u.Packet_Downlink_Ack_Nack, fn);
+		break;
+	case MT_EGPRS_PACKET_DOWNLINK_ACK_NACK:
+		rcv_control_egprs_dl_ack_nack(&ul_control_block->u.Egprs_Packet_Downlink_Ack_Nack, fn);
+		break;
+	case MT_PACKET_RESOURCE_REQUEST:
+		rcv_resource_request(&ul_control_block->u.Packet_Resource_Request, fn);
+		break;
+	case MT_PACKET_MEASUREMENT_REPORT:
+		rcv_measurement_report(&ul_control_block->u.Packet_Measurement_Report, fn);
+		break;
+	case MT_PACKET_UPLINK_DUMMY_CONTROL_BLOCK:
+		/* ignoring it. change the SI to not force sending these? */
+		break;
+	default:
+		bts()->decode_error();
+		LOGP(DRLCMAC, LOGL_NOTICE,
+			"RX: [PCU <- BTS] unknown control block(%d) received\n",
+			ul_control_block->u.MESSAGE_TYPE);
+	}
+	talloc_free(ul_control_block);
+	return 1;
+}
+
+
+/* received RLC/MAC block from L1 */
+int gprs_rlcmac_pdch::rcv_block(uint8_t *data, uint8_t len, uint32_t fn,
+	struct pcu_l1_meas *meas)
+{
+	GprsCodingScheme cs = GprsCodingScheme::getBySizeUL(len);
+	if (!cs) {
+		bts()->decode_error();
+		LOGP(DRLCMACUL, LOGL_ERROR, "Dropping data block with invalid"
+			"length: %d)\n", len);
+		return -EINVAL;
+	}
+
+	bts()->rlc_ul_bytes(len);
+
+	LOGP(DRLCMACUL, LOGL_DEBUG, "Got RLC block, coding scheme: %s, "
+		"length: %d (%d))\n", cs.name(), len, cs.usedSizeUL());
+
+	if (cs.isGprs())
+		return rcv_block_gprs(data, fn, meas, cs);
+
+	if (cs.isEgprs())
+		return rcv_data_block(data, fn, meas, cs);
+
+	bts()->decode_error();
+	LOGP(DRLCMACUL, LOGL_ERROR, "Unsupported coding scheme %s\n",
+		cs.name());
+	return -EINVAL;
+}
+
+/*! \brief process egprs and gprs data blocks */
+int gprs_rlcmac_pdch::rcv_data_block(uint8_t *data, uint32_t fn,
+	struct pcu_l1_meas *meas, GprsCodingScheme cs)
+{
+	int rc;
+	struct gprs_rlc_data_info rlc_dec;
+	struct gprs_rlcmac_ul_tbf *tbf;
+	unsigned len = cs.sizeUL();
+
+	/* These are always data blocks, since EGPRS still uses CS-1 for
+	 * control blocks (see 44.060, section 10.3, 1st par.)
+	 */
+	if (cs.isEgprs()) {
+		if (!bts()->bts_data()->egprs_enabled) {
+			LOGP(DRLCMACUL, LOGL_ERROR,
+				"Got %s RLC block but EGPRS is not enabled\n",
+				cs.name());
+			return -EINVAL;
+		}
+	}
+
+	LOGP(DRLCMACUL, LOGL_DEBUG, "  UL data: %s\n", osmo_hexdump(data, len));
+	rc = Decoding::rlc_parse_ul_data_header(&rlc_dec, data, cs);
+	if (rc < 0) {
+		LOGP(DRLCMAC, LOGL_ERROR,
+			"Got %s RLC block but header parsing has failed\n",
+			cs.name());
+		bts()->decode_error();
+		return rc;
+	}
+
+	LOGP(DRLCMACUL, LOGL_INFO,
+		"Got %s RLC block: "
+		"R=%d, SI=%d, TFI=%d, CPS=%d, RSB=%d, "
+		"rc=%d\n",
+		cs.name(),
+		rlc_dec.r, rlc_dec.si, rlc_dec.tfi, rlc_dec.cps, rlc_dec.rsb,
+		rc);
+
+	/* find TBF inst from given TFI */
+	tbf = ul_tbf_by_tfi(rlc_dec.tfi);
+	if (!tbf) {
+		LOGP(DRLCMAC, LOGL_NOTICE, "UL DATA unknown TFI=%d\n",
+			rlc_dec.tfi);
+		return 0;
+	}
+	LOGP(DRLCMAC, LOGL_DEBUG, "[RX: PCU <- BTS] %s UL data\n", tbf->name());
+
+	return tbf->rcv_data_block_acknowledged(&rlc_dec, data, meas);
+}
+
+int gprs_rlcmac_pdch::rcv_block_gprs(uint8_t *data, uint32_t fn,
+	struct pcu_l1_meas *meas, GprsCodingScheme cs)
+{
+	unsigned payload = data[0] >> 6;
+	bitvec *block;
+	int rc = 0;
+	unsigned len = cs.maxBytesUL();
+
+	switch (payload) {
+	case GPRS_RLCMAC_DATA_BLOCK:
+		rc = rcv_data_block(data, fn, meas, cs);
+		break;
+	case GPRS_RLCMAC_CONTROL_BLOCK:
+		block = bitvec_alloc(len);
+		if (!block)
+			return -ENOMEM;
+		bitvec_unpack(block, data);
+		rc = rcv_control_block(block, fn);
+		bitvec_free(block);
+		break;
+	case GPRS_RLCMAC_CONTROL_BLOCK_OPT:
+		LOGP(DRLCMAC, LOGL_NOTICE, "GPRS_RLCMAC_CONTROL_BLOCK_OPT block payload is not supported.\n");
+		break;
+	default:
+		LOGP(DRLCMAC, LOGL_NOTICE, "Unknown RLCMAC block payload(%u).\n", payload);
+		rc = -EINVAL;
+	}
+
+	return rc;
+}
+
+void bts_update_tbf_ta(const char *p, uint32_t fn, uint8_t trx_no, uint8_t ts,
+		       uint8_t ta)
+{
+	struct gprs_rlcmac_ul_tbf *tbf =
+		bts_main_data()->bts->ul_tbf_by_poll_fn(fn, trx_no, ts);
+	if (!tbf)
+		LOGP(DL1IF, LOGL_DEBUG, "[%s] update TA = %u ignored due to "
+		     "unknown UL TBF on TRX = %d, TS = %d, FN = %d\n",
+		     p, ta, trx_no, ts, fn);
+	else if (tbf->ta() != ta) {
+		LOGP(DL1IF, LOGL_INFO, "[%s] Updating TA %u -> %u on "
+		     "TRX = %d, TS = %d, FN = %d\n",
+		     p, tbf->ta(), ta, trx_no, ts, fn);
+		tbf->set_ta(ta);
+	}
+}
+
+gprs_rlcmac_tbf *gprs_rlcmac_pdch::tbf_from_list_by_tfi(
+		LListHead<gprs_rlcmac_tbf> *tbf_list, uint8_t tfi,
+		enum gprs_rlcmac_tbf_direction dir)
+{
+	gprs_rlcmac_tbf *tbf;
+	LListHead<gprs_rlcmac_tbf> *pos;
+
+	llist_for_each(pos, tbf_list) {
+		tbf = pos->entry();
+		if (tbf->tfi() != tfi)
+			continue;
+		if (!tbf->pdch[ts_no])
+			continue;
+		return tbf;
+	}
+	return NULL;
+}
+
+gprs_rlcmac_ul_tbf *gprs_rlcmac_pdch::ul_tbf_by_tfi(uint8_t tfi)
+{
+	return as_ul_tbf(tbf_by_tfi(tfi, GPRS_RLCMAC_UL_TBF));
+}
+
+gprs_rlcmac_dl_tbf *gprs_rlcmac_pdch::dl_tbf_by_tfi(uint8_t tfi)
+{
+	return as_dl_tbf(tbf_by_tfi(tfi, GPRS_RLCMAC_DL_TBF));
+}
+
+/* lookup TBF Entity (by TFI) */
+gprs_rlcmac_tbf *gprs_rlcmac_pdch::tbf_by_tfi(uint8_t tfi,
+	enum gprs_rlcmac_tbf_direction dir)
+{
+	struct gprs_rlcmac_tbf *tbf;
+
+	if (tfi >= 32)
+		return NULL;
+
+	tbf = m_tbfs[dir][tfi];
+
+	if (!tbf)
+		return NULL;
+
+	if (tbf->state_is_not(GPRS_RLCMAC_RELEASING)) {
+		return tbf;
+	}
+
+	return NULL;
+}
+
+void gprs_rlcmac_pdch::attach_tbf(gprs_rlcmac_tbf *tbf)
+{
+	gprs_rlcmac_ul_tbf *ul_tbf;
+
+	if (m_tbfs[tbf->direction][tbf->tfi()])
+		LOGP(DRLCMAC, LOGL_ERROR, "PDCH(TS %d, TRX %d): "
+			"%s has not been detached, overwriting it\n",
+			ts_no, trx_no(),
+			m_tbfs[tbf->direction][tbf->tfi()]->name());
+
+	m_num_tbfs[tbf->direction] += 1;
+	if (tbf->direction == GPRS_RLCMAC_UL_TBF) {
+		ul_tbf = as_ul_tbf(tbf);
+		m_assigned_usf |= 1 << ul_tbf->m_usf[ts_no];
+	}
+	m_assigned_tfi[tbf->direction] |= 1UL << tbf->tfi();
+	m_tbfs[tbf->direction][tbf->tfi()] = tbf;
+
+	LOGP(DRLCMAC, LOGL_INFO, "PDCH(TS %d, TRX %d): Attaching %s, %d TBFs, "
+		"USFs = %02x, TFIs = %08x.\n",
+		ts_no, trx_no(), tbf->name(), m_num_tbfs[tbf->direction],
+		m_assigned_usf, m_assigned_tfi[tbf->direction]);
+}
+
+void gprs_rlcmac_pdch::detach_tbf(gprs_rlcmac_tbf *tbf)
+{
+	gprs_rlcmac_ul_tbf *ul_tbf;
+
+	OSMO_ASSERT(m_num_tbfs[tbf->direction] > 0);
+
+	m_num_tbfs[tbf->direction] -= 1;
+	if (tbf->direction == GPRS_RLCMAC_UL_TBF) {
+		ul_tbf = as_ul_tbf(tbf);
+		m_assigned_usf &= ~(1 << ul_tbf->m_usf[ts_no]);
+	}
+	m_assigned_tfi[tbf->direction] &= ~(1UL << tbf->tfi());
+	m_tbfs[tbf->direction][tbf->tfi()] = NULL;
+
+	LOGP(DRLCMAC, LOGL_INFO, "PDCH(TS %d, TRX %d): Detaching %s, %d TBFs, "
+		"USFs = %02x, TFIs = %08x.\n",
+		ts_no, trx_no(), tbf->name(), m_num_tbfs[tbf->direction],
+		m_assigned_usf, m_assigned_tfi[tbf->direction]);
+}
+
+void gprs_rlcmac_pdch::reserve(enum gprs_rlcmac_tbf_direction dir)
+{
+	m_num_reserved[dir] += 1;
+}
+
+void gprs_rlcmac_pdch::unreserve(enum gprs_rlcmac_tbf_direction dir)
+{
+	OSMO_ASSERT(m_num_reserved[dir] > 0);
+	m_num_reserved[dir] -= 1;
+}
+
+void gprs_rlcmac_trx::reserve_slots(enum gprs_rlcmac_tbf_direction dir,
+	uint8_t slots)
+{
+	unsigned i;
+	for (i = 0; i < ARRAY_SIZE(pdch); i += 1)
+		if (slots & (1 << i))
+			pdch[i].reserve(dir);
+}
+
+void gprs_rlcmac_trx::unreserve_slots(enum gprs_rlcmac_tbf_direction dir,
+	uint8_t slots)
+{
+	unsigned i;
+	for (i = 0; i < ARRAY_SIZE(pdch); i += 1)
+		if (slots & (1 << i))
+			pdch[i].unreserve(dir);
+}
diff --git a/src/csn1.cpp b/src/csn1.cpp
index a1698a5..6203a44 100644
--- a/src/csn1.cpp
+++ b/src/csn1.cpp
@@ -64,15 +64,15 @@
   readIndex -= relative_bit_offset;
   if (bit_shift >= 0)
   {
-    result = (0x2B ^ ((guint8)bitvec_read_field(vector, readIndex, 8))) >> bit_shift;
+    result = (0x2B ^ ((guint8)bitvec_read_field(vector, &readIndex, 8))) >> bit_shift;
     readIndex-= bit_shift;
     result &= maskBits[no_of_bits];
   }
   else
   { 
-    guint8 hight_part = (0x2B ^ ((guint8)bitvec_read_field(vector, readIndex, 8))) & maskBits[8 - relative_bit_offset];
+    guint8 hight_part = (0x2B ^ ((guint8)bitvec_read_field(vector, &readIndex, 8))) & maskBits[8 - relative_bit_offset];
     hight_part = (guint8) (hight_part << (-bit_shift));
-    result =  (0x2B ^ ((guint8)bitvec_read_field(vector, readIndex, 8))) >> (8 + bit_shift);
+    result =  (0x2B ^ ((guint8)bitvec_read_field(vector, &readIndex, 8))) >> (8 + bit_shift);
     readIndex = readIndex - (8 - (-bit_shift));
     result |= hight_part;
   }
@@ -133,7 +133,7 @@
 static gboolean
 existNextElement(bitvec *vector, unsigned& readIndex, guint8 Tag)
 {
-  guint8 res = bitvec_read_field(vector, readIndex, 1);
+  guint8 res = bitvec_read_field(vector, &readIndex, 1);
   if (Tag == STANDARD_TAG)
   {
     return (res > 0);
@@ -167,7 +167,7 @@
         if (remaining_bits_len > 0)
         {
           pui8  = pui8DATA(data, pDescr->offset);
-          *pui8 = bitvec_read_field(vector, readIndex, 1);
+	  *pui8 = bitvec_read_field(vector, &readIndex, 1);
           LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
           /* end add the bit value to protocol tree */
         }
@@ -202,21 +202,21 @@
         {
           if (no_of_bits <= 8)
           {
-            guint8 ui8 = bitvec_read_field(vector, readIndex, no_of_bits);
+	    guint8 ui8 = bitvec_read_field(vector, &readIndex, no_of_bits);
             pui8      = pui8DATA(data, pDescr->offset);
             *pui8     = ui8;
             LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
           }
           else if (no_of_bits <= 16)
           {
-            guint16 ui16 = bitvec_read_field(vector, readIndex, no_of_bits);
+	    guint16 ui16 = bitvec_read_field(vector, &readIndex, no_of_bits);
             pui16       = pui16DATA(data, pDescr->offset);
             *pui16      = ui16;
             LOGPC(DCSN1, LOGL_NOTICE, "%s = %d | ", pDescr->sz , *pui16);
           }
           else if (no_of_bits <= 32)
           {
-            guint32 ui32 = bitvec_read_field(vector, readIndex, no_of_bits);
+	    guint32 ui32 = bitvec_read_field(vector, &readIndex, no_of_bits);
             pui32       = pui32DATA(data, pDescr->offset);
             *pui32      = ui32;
             LOGPC(DCSN1, LOGL_NOTICE, "%s = 0x%08x | ", pDescr->sz , *pui32);
@@ -264,21 +264,21 @@
         {
           if (no_of_bits <= 8)
           {
-            guint8 ui8 = bitvec_read_field(vector, readIndex, no_of_bits);
+	    guint8 ui8 = bitvec_read_field(vector, &readIndex, no_of_bits);
             pui8      = pui8DATA(data, pDescr->offset);
             *pui8     = ui8 + (guint8)pDescr->descr.value;
             LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
           }
           else if (no_of_bits <= 16)
           {
-            guint16 ui16 = bitvec_read_field(vector, readIndex, no_of_bits);
+	    guint16 ui16 = bitvec_read_field(vector, &readIndex, no_of_bits);
             pui16       = pui16DATA(data, pDescr->offset);
             *pui16      = ui16 + (guint16)pDescr->descr.value;
             LOGPC(DCSN1, LOGL_NOTICE, "%s = %d | ", pDescr->sz , *pui16);
           }
           else if (no_of_bits <= 32)
           {
-            guint32 ui32 = bitvec_read_field(vector, readIndex, no_of_bits);
+	    guint32 ui32 = bitvec_read_field(vector, &readIndex, no_of_bits);
             pui32       = pui32DATA(data, pDescr->offset);
             *pui32      = ui32 + (guint16)pDescr->descr.value;
             LOGPC(DCSN1, LOGL_NOTICE, "%s = %d | ", pDescr->sz , *pui32);
@@ -308,7 +308,7 @@
           remaining_bits_len -= no_of_bits;
           if (no_of_bits <= 8)
           {
-            guint8 ui8 = get_masked_bits8(vector, readIndex, bit_offset, no_of_bits);
+	    guint8 ui8 = get_masked_bits8(vector, readIndex, bit_offset, no_of_bits);
             pui8      = pui8DATA(data, pDescr->offset);
             *pui8     = ui8;
             LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
@@ -347,7 +347,7 @@
             pui8 = pui8DATA(data, pDescr->offset);
             do
             {
-              *pui8 = bitvec_read_field(vector, readIndex, no_of_bits);
+	      *pui8 = bitvec_read_field(vector, &readIndex, no_of_bits);
               LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
               pui8++;
               bit_offset += no_of_bits;
@@ -401,7 +401,7 @@
 
           LOGPC(DCSN1, LOGL_NOTICE, "%s | ", pDescr->sz);
           csnStreamInit(&arT, bit_offset, remaining_bits_len);
-          Status = csnStreamDecoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, readIndex, pui8);
+	  Status = csnStreamDecoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, readIndex, pui8);
           if (Status >= 0)
           {
             pui8    += nSize;
@@ -430,7 +430,7 @@
           {
             for(unsigned ib = 0; ib < 4; ib++)
             {
-              guint8 ui8 = bitvec_read_field(vector, readIndex, 8);
+	      guint8 ui8 = bitvec_read_field(vector, &readIndex, 8);
               pui8      = pui8DATA(data, pDescr->offset+ib);
               *pui8      = ui8;
                LOGPC(DCSN1, LOGL_NOTICE, "%s[%u] = %u | ", pDescr->sz , ib, (unsigned)*pui8);
@@ -440,7 +440,7 @@
           {
             for(unsigned ib = 0; ib < 8; ib++)
             {
-              guint8 ui8 = bitvec_read_field(vector, readIndex, 8);
+	      guint8 ui8 = bitvec_read_field(vector, &readIndex, 8);
               pui8      = pui8DATA(data, pDescr->offset+ib);
               *pui8      = ui8;
                LOGPC(DCSN1, LOGL_NOTICE, "%s[%u] = %u | ", pDescr->sz , ib, (unsigned)*pui8);
@@ -467,7 +467,7 @@
         csnStream_t arT = *ar;
         LOGPC(DCSN1, LOGL_NOTICE, " : %s | ", pDescr->sz);
         csnStreamInit(&arT, bit_offset, remaining_bits_len);
-        Status = csnStreamDecoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, readIndex, pvDATA(data, pDescr->offset));
+	Status = csnStreamDecoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, readIndex, pvDATA(data, pDescr->offset));
         LOGPC(DCSN1, LOGL_NOTICE, ": End %s | ", pDescr->sz);
         if (Status >= 0)
         {
@@ -493,7 +493,7 @@
         while (count > 0)
         {
           guint8 no_of_bits = pChoice->bits;
-          guint8 value = bitvec_read_field(vector, readIndex, no_of_bits);
+	  guint8 value = bitvec_read_field(vector, &readIndex, no_of_bits);
           if (value == pChoice->value)
           {
             CSN_DESCR   descr[2];
@@ -510,7 +510,7 @@
             remaining_bits_len -= no_of_bits;
 
             csnStreamInit(&arT, bit_offset, remaining_bits_len);
-            Status = csnStreamDecoder(&arT, descr, vector, readIndex, data);
+	    Status = csnStreamDecoder(&arT, descr, vector, readIndex, data);
 
             if (Status >= 0)
             {
@@ -541,7 +541,7 @@
         guint8 length_len              = pDescr->i;
         gint16               Status    = -1;
 
-        guint8 length = bitvec_read_field(vector, readIndex, length_len);
+	guint8 length = bitvec_read_field(vector, &readIndex, length_len);
 
         LOGPC(DCSN1, LOGL_NOTICE, "%s length = %d | ", pDescr->sz , (int)length);
         bit_offset += length_len;
@@ -550,7 +550,7 @@
         csnStreamInit(&arT, bit_offset, length);
         arT.direction = 1;
         LOGPC(DCSN1, LOGL_NOTICE, "ptr = %p | offset = %d | ", (void *)data, (int)pDescr->offset);
-        Status = serialize(&arT, vector, readIndex, pvDATA(data, pDescr->offset));
+	Status = serialize(&arT, vector, readIndex, pvDATA(data, pDescr->offset));
 
         if (Status >= 0)
         {
@@ -595,7 +595,7 @@
           }
           else
           {
-            index |= bitvec_read_field(vector, readIndex, 1);
+	    index |= bitvec_read_field(vector, &readIndex, 1);
           }
           remaining_bits_len--;
           bit_offset++;
@@ -618,7 +618,7 @@
           {
             pui8  = pui8DATA(data, pDescr->offset);
             *pui8 = 0x00;
-            if (bitvec_read_field(vector, readIndex, 1) > 0)
+	    if (bitvec_read_field(vector, &readIndex, 1) > 0)
             {
               *pui8 = 0x01;
             }
@@ -644,21 +644,21 @@
 
               if (no_of_bits <= 8)
               {
-                guint8 ui8 = bitvec_read_field(vector, readIndex,  no_of_bits);
+		guint8 ui8 = bitvec_read_field(vector, &readIndex,  no_of_bits);
                 pui8       = pui8DATA(data, pDescr->offset);
                 *pui8      = ui8;
                 LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
               }
               else if (no_of_bits <= 16)
               {
-                guint16 ui16 = bitvec_read_field(vector, readIndex,  no_of_bits);
+		guint16 ui16 = bitvec_read_field(vector, &readIndex,  no_of_bits);
                 pui16        = pui16DATA(data, pDescr->offset);
                 *pui16       = ui16;
                 LOGPC(DCSN1, LOGL_NOTICE, "%s = %d | ", pDescr->sz , *pui16);
               }
               else if (no_of_bits <= 32)
               {
-                guint32 ui32 = bitvec_read_field(vector, readIndex,  no_of_bits);
+		guint32 ui32 = bitvec_read_field(vector, &readIndex,  no_of_bits);
                 pui32       = pui32DATA(data, pDescr->offset);
                 *pui32      = ui32;
                 LOGPC(DCSN1, LOGL_NOTICE, "%s = %d | ", pDescr->sz , *pui32);
@@ -686,21 +686,21 @@
             {
               if (no_of_bits <= 8)
               {
-                guint8 ui8 = bitvec_read_field(vector, readIndex,  no_of_bits);
+		guint8 ui8 = bitvec_read_field(vector, &readIndex,  no_of_bits);
                 pui8      = pui8DATA(data, pDescr->offset);
                 *pui8     = ui8 + (guint8)pDescr->descr.value;
                 LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
               }
               else if (no_of_bits <= 16)
               {
-                guint16 ui16 = bitvec_read_field(vector, readIndex,  no_of_bits);
+		guint16 ui16 = bitvec_read_field(vector, &readIndex,  no_of_bits);
                 pui16       = pui16DATA(data, pDescr->offset);
                 *pui16      = ui16 + (guint16)pDescr->descr.value;
                 LOGPC(DCSN1, LOGL_NOTICE, "%s = %d | ", pDescr->sz , *pui16);
               }
               else if (no_of_bits <= 32)
               {
-                guint32 ui32 = bitvec_read_field(vector, readIndex,  no_of_bits);
+		guint32 ui32 = bitvec_read_field(vector, &readIndex,  no_of_bits);
                 pui32       = pui32DATA(data, pDescr->offset);
                 *pui32      = ui32 + (guint16)pDescr->descr.value;
                 LOGPC(DCSN1, LOGL_NOTICE, "%s = %d | ", pDescr->sz , *pui32);
@@ -728,7 +728,7 @@
             {
               if (no_of_bits <= 8)
               {
-                guint8 ui8 = get_masked_bits8(vector, readIndex, bit_offset, no_of_bits);
+		guint8 ui8 = get_masked_bits8(vector, readIndex, bit_offset, no_of_bits);
                 pui8      = pui8DATA(data, pDescr->offset);
                 *pui8     = ui8;
                 LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
@@ -767,7 +767,7 @@
 
                 while (nCount > 0)
                 {
-                  *pui8 = bitvec_read_field(vector, readIndex,  no_of_bits);
+		  *pui8 = bitvec_read_field(vector, &readIndex,  no_of_bits);
                   LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
                   pui8++;
                   bit_offset += no_of_bits;
@@ -780,7 +780,7 @@
 
                 while (nCount > 0)
                 {
-                 *pui16 = bitvec_read_field(vector, readIndex,  no_of_bits);
+		 *pui16 = bitvec_read_field(vector, &readIndex,  no_of_bits);
                   LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pDescr->sz , *pui16);
                   pui16++;
                   bit_offset += no_of_bits;
@@ -830,7 +830,7 @@
             {
               LOGPC(DCSN1, LOGL_NOTICE, "%s | ", pDescr->sz);
               csnStreamInit(&arT, bit_offset, remaining_bits_len);
-              Status = csnStreamDecoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, readIndex, pui8);
+	      Status = csnStreamDecoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, readIndex, pui8);
               if (Status >= 0)
               {
                 pui8    += nSize;
@@ -856,13 +856,13 @@
 
               if (no_of_bits <= 32)
               {
-                guint32 ui32 = bitvec_read_field(vector, readIndex, no_of_bits);
+		guint32 ui32 = bitvec_read_field(vector, &readIndex, no_of_bits);
                 pui32       = pui32DATA(data, pDescr->offset);
                 *pui32      = ui32;
               }
               else if (no_of_bits <= 64)
               {
-                guint64 ui64 = bitvec_read_field(vector, readIndex, no_of_bits);
+		guint64 ui64 = bitvec_read_field(vector, &readIndex, no_of_bits);
                 pui64       = pui64DATA(data, pDescr->offset);
                 *pui64      = ui64;
                 LOGPC(DCSN1, LOGL_NOTICE, "%s = %lu | ", pDescr->sz , *pui64);
@@ -888,7 +888,7 @@
             csnStream_t arT = *ar;
             LOGPC(DCSN1, LOGL_NOTICE, " : %s | ", pDescr->sz);
             csnStreamInit(&arT, bit_offset, remaining_bits_len);
-            Status = csnStreamDecoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, readIndex, pvDATA(data, pDescr->offset));
+	    Status = csnStreamDecoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, readIndex, pvDATA(data, pDescr->offset));
             LOGPC(DCSN1, LOGL_NOTICE, " : End %s | ", pDescr->sz);
             if (Status >= 0)
             {
@@ -923,11 +923,11 @@
 
         if (CSN_EXIST_LH == pDescr->type)
         {
-          fExist = get_masked_bits8(vector, readIndex, bit_offset, 1);
+	  fExist = get_masked_bits8(vector, readIndex, bit_offset, 1);
         }
         else
         {
-          fExist = bitvec_read_field(vector, readIndex, 1);
+	  fExist = bitvec_read_field(vector, &readIndex, 1);
         }
 
         *pui8 = fExist;
@@ -966,7 +966,7 @@
         /* the "regular" M_NEXT_EXIST description element */
 
         fExist = 0x00;
-        if (bitvec_read_field(vector, readIndex, 1))
+	if (bitvec_read_field(vector, &readIndex, 1))
         {
           fExist = 0x01;
         }
@@ -1059,7 +1059,7 @@
 
             if (nB1 > 0)
             { /* take care of the first byte - it will be right aligned */
-              *pui8 = bitvec_read_field(vector, readIndex, nB1);
+	      *pui8 = bitvec_read_field(vector, &readIndex, nB1);
               LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
               pui8++;
               no_of_bits  -= nB1;
@@ -1069,7 +1069,7 @@
             /* remaining no_of_bits is a multiple of 8 or 0 */
             while (no_of_bits > 0)
             {
-              *pui8 = bitvec_read_field(vector, readIndex, 8);
+	      *pui8 = bitvec_read_field(vector, &readIndex, 8);
               LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
               pui8++;
               no_of_bits -= 8;
@@ -1113,14 +1113,14 @@
 
             while (no_of_bits >= 8)
             {
-              *pui8 = bitvec_read_field(vector, readIndex, 8);
+	      *pui8 = bitvec_read_field(vector, &readIndex, 8);
               LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
               pui8++;
               no_of_bits -= 8;
             }
             if (no_of_bits > 0)
             { 
-              *pui8 = bitvec_read_field(vector, readIndex, no_of_bits);
+	      *pui8 = bitvec_read_field(vector, &readIndex, no_of_bits);
               LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
               pui8++;
               bit_offset += no_of_bits;
@@ -1144,13 +1144,13 @@
             guint8 bits_to_handle = remaining_bits_len%8;
             if (bits_to_handle > 0)
             {
-              LOGPC(DCSN1, LOGL_NOTICE, "%" PRIu64 "|", bitvec_read_field(vector, readIndex, bits_to_handle));
+	      LOGPC(DCSN1, LOGL_NOTICE, "%" PRIu64 "|", bitvec_read_field(vector, &readIndex, bits_to_handle));
               remaining_bits_len -= bits_to_handle;
               bit_offset += bits_to_handle;
             }
             else if (bits_to_handle == 0)
             {
-              LOGPC(DCSN1, LOGL_NOTICE, "%" PRIu64 "|", bitvec_read_field(vector, readIndex, 8));
+	      LOGPC(DCSN1, LOGL_NOTICE, "%" PRIu64 "|", bitvec_read_field(vector, &readIndex, 8));
               remaining_bits_len -= 8;
               bit_offset += 8;
             }
@@ -1191,7 +1191,7 @@
           while (count > 0)
           {
             readIndex -= 8;
-            *pui8 = bitvec_read_field(vector, readIndex, 8);
+	    *pui8 = bitvec_read_field(vector, &readIndex, 8);
             LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
             pui8++;
             bit_offset += 8;
@@ -1217,14 +1217,14 @@
 
         pui8  = pui8DATA(data, pDescr->offset);
 
-        while (existNextElement(vector, readIndex, Tag))
+	while (existNextElement(vector, readIndex, Tag))
         { /* tag control shows existence of next list elements */
           LOGPC(DCSN1, LOGL_NOTICE, "%s = Exist | ", pDescr->sz);
           bit_offset++;
           remaining_bits_len--;
 
           /* extract and store no_of_bits long element from bitstream */
-          *pui8 = bitvec_read_field(vector, readIndex, no_of_bits);
+	  *pui8 = bitvec_read_field(vector, &readIndex, no_of_bits);
           LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
           pui8++;
           remaining_bits_len -= no_of_bits;
@@ -1238,7 +1238,7 @@
           bit_offset += no_of_bits;
         }
 
-        LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pDescr->sz , (unsigned)bitvec_read_field(vector, readIndex, 1));
+	LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pDescr->sz , (unsigned)bitvec_read_field(vector, &readIndex, 1));
         /* existNextElement() returned FALSE, 1 bit consumed */
         bit_offset++;
 
@@ -1258,7 +1258,7 @@
         guint8  ElementCount = 0;
         pui8  = pui8DATA(data, pDescr->offset);
 
-        while (existNextElement(vector, readIndex, Tag))
+	while (existNextElement(vector, readIndex, Tag))
         { /* tag control shows existence of next list elements */
           LOGPC(DCSN1, LOGL_NOTICE, "%s = Exist | ", pDescr->sz);
           /* existNextElement() returned TRUE, 1 bit consumed */
@@ -1270,7 +1270,7 @@
             csnStream_t arT = *ar;
             gint16      Status;
             csnStreamInit(&arT, bit_offset, remaining_bits_len);
-            Status = csnStreamDecoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, readIndex, pui8);
+	    Status = csnStreamDecoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, readIndex, pui8);
 
             if (Status >= 0)
             { /* successful completion */
@@ -1290,7 +1290,7 @@
           }
         }
 
-        LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pDescr->sz , (unsigned)bitvec_read_field(vector, readIndex, 1));
+	LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pDescr->sz , (unsigned)bitvec_read_field(vector, &readIndex, 1));
 
         /* existNextElement() returned FALSE, 1 bit consumed */
         bit_offset++;
@@ -1331,7 +1331,7 @@
           LOGPC(DCSN1, LOGL_NOTICE, "%s { | ", pDescr->sz);
           
           csnStreamInit(&arT, bit_offset, remaining_bits_len);
-          Status = csnStreamDecoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, readIndex, pui8);
+	  Status = csnStreamDecoder(&arT, (const CSN_DESCR*)pDescr->descr.ptr, vector, readIndex, pui8);
 
           if (Status >= 0)
           { /* successful completion */
@@ -1351,7 +1351,7 @@
 
           /* control of next element's tag */
           LOGPC(DCSN1, LOGL_NOTICE, "%s } | ", pDescr->sz);
-          EndOfList         = !(existNextElement(vector, readIndex, Tag));
+	  EndOfList         = !(existNextElement(vector, readIndex, Tag));
 
           bit_offset++;
           remaining_bits_len--; /* 1 bit consumed (tag) */
@@ -1372,7 +1372,7 @@
 
         if (no_of_bits <= 32)
         {
-          ui32 = bitvec_read_field(vector, readIndex, no_of_bits);
+	  ui32 = bitvec_read_field(vector, &readIndex, no_of_bits);
         }
         else
         {
@@ -1449,7 +1449,7 @@
         if (remaining_bits_len > 0)
         {
           pui8  = pui8DATA(data, pDescr->offset);
-          bitvec_write_field(vector, writeIndex, *pui8, 1);
+	  bitvec_write_field(vector, &writeIndex, *pui8, 1);
           LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
           /* end add the bit value to protocol tree */
         }
@@ -1483,19 +1483,19 @@
           if (no_of_bits <= 8)
           {
             pui8      = pui8DATA(data, pDescr->offset);
-            bitvec_write_field(vector, writeIndex, *pui8, no_of_bits);
+	    bitvec_write_field(vector, &writeIndex, *pui8, no_of_bits);
             LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
           }
           else if (no_of_bits <= 16)
           {
             pui16       = pui16DATA(data, pDescr->offset);
-            bitvec_write_field(vector, writeIndex, *pui16, no_of_bits);
+	    bitvec_write_field(vector, &writeIndex, *pui16, no_of_bits);
             LOGPC(DCSN1, LOGL_NOTICE, "%s = %d | ", pDescr->sz , *pui16);
           }
           else if (no_of_bits <= 32)
           {
             pui32       = pui32DATA(data, pDescr->offset);
-            bitvec_write_field(vector, writeIndex, *pui32, no_of_bits);
+	    bitvec_write_field(vector, &writeIndex, *pui32, no_of_bits);
             LOGPC(DCSN1, LOGL_NOTICE, "%s = %d | ", pDescr->sz , *pui32);
           }
           else
@@ -1528,19 +1528,19 @@
           if (no_of_bits <= 8)
           {
             pui8      = pui8DATA(data, pDescr->offset);
-            bitvec_write_field(vector, writeIndex, *pui8 - (guint8)pDescr->descr.value, no_of_bits);
+	    bitvec_write_field(vector, &writeIndex, *pui8 - (guint8)pDescr->descr.value, no_of_bits);
             LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pDescr->sz , (unsigned)(*pui8 - (guint8)pDescr->descr.value));
           }
           else if (no_of_bits <= 16)
           {
             pui16       = pui16DATA(data, pDescr->offset);
-            bitvec_write_field(vector, writeIndex, *pui16 - (guint16)pDescr->descr.value, no_of_bits);
+	    bitvec_write_field(vector, &writeIndex, *pui16 - (guint16)pDescr->descr.value, no_of_bits);
             LOGPC(DCSN1, LOGL_NOTICE, "%s = %d | ", pDescr->sz , (unsigned short)(*pui16 - (guint16)pDescr->descr.value));
           }
           else if (no_of_bits <= 32)
           {
             pui32       = pui32DATA(data, pDescr->offset);
-            bitvec_write_field(vector, writeIndex, *pui32 - (guint16)pDescr->descr.value, no_of_bits);
+	    bitvec_write_field(vector, &writeIndex, *pui32 - (guint16)pDescr->descr.value, no_of_bits);
             LOGPC(DCSN1, LOGL_NOTICE, "%s = %d | ", pDescr->sz , (unsigned int)(*pui32 - (guint16)pDescr->descr.value));
           }
           else
@@ -1569,12 +1569,12 @@
           if (no_of_bits <= 8)
           {
             pui8      = pui8DATA(data, pDescr->offset);
-            bitvec_write_field(vector, writeIndex, *pui8, no_of_bits);
+	    bitvec_write_field(vector, &writeIndex, *pui8, no_of_bits);
             // TODO : Change get_masked_bits8()
             writeIndex -= no_of_bits;
             guint8 ui8 = get_masked_bits8(vector, writeIndex, bit_offset, no_of_bits);
             writeIndex -= no_of_bits;
-            bitvec_write_field(vector, writeIndex, ui8, no_of_bits);
+	    bitvec_write_field(vector, &writeIndex, ui8, no_of_bits);
             LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
 
           }
@@ -1612,7 +1612,7 @@
             pui8 = pui8DATA(data, pDescr->offset);
             do
             {
-              bitvec_write_field(vector, writeIndex, *pui8, no_of_bits);
+	      bitvec_write_field(vector, &writeIndex, *pui8, no_of_bits);
               LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
               pui8++;
               bit_offset += no_of_bits;
@@ -1697,7 +1697,7 @@
             for(unsigned ib = 0; ib < 4; ib++)
             {
               pui8      = pui8DATA(data, pDescr->offset+ib);
-              bitvec_write_field(vector, writeIndex, *pui8, 8);
+	      bitvec_write_field(vector, &writeIndex, *pui8, 8);
               LOGPC(DCSN1, LOGL_NOTICE, "%s[%u] = %u | ", pDescr->sz , ib, (unsigned)*pui8);
             }
           }
@@ -1706,7 +1706,7 @@
             for(unsigned ib = 0; ib < 8; ib++)
             {
               pui8      = pui8DATA(data, pDescr->offset+ib);
-              bitvec_write_field(vector, writeIndex, *pui8, 8);
+	      bitvec_write_field(vector, &writeIndex, *pui8, 8);
               LOGPC(DCSN1, LOGL_NOTICE, "%s[%u] = %u | ", pDescr->sz , ib, (unsigned)*pui8);
             }
           }
@@ -1761,7 +1761,7 @@
         guint8 no_of_bits = pChoice->bits;
         guint8 value = pChoice->value;
         LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pChoice->descr.sz , (unsigned)value);
-        bitvec_write_field(vector, writeIndex, value, no_of_bits);
+	bitvec_write_field(vector, &writeIndex, value, no_of_bits);
 
         CSN_DESCR   descr[2];
         gint16      Status;
@@ -1807,7 +1807,7 @@
         csnStreamInit(&arT, bit_offset, remaining_bits_len);
         Status = serialize(&arT, vector, writeIndex, pvDATA(data, pDescr->offset));
 
-        bitvec_write_field(vector, lengthIndex, writeIndex-lengthIndex-length_len, length_len);
+	bitvec_write_field(vector, &lengthIndex, writeIndex-lengthIndex-length_len, length_len);
         LOGPC(DCSN1, LOGL_NOTICE, "%s length = %u | ", pDescr->sz , (unsigned)(writeIndex-lengthIndex));
 
         if (Status >= 0)
@@ -1846,7 +1846,7 @@
         /* Assign UnionType */
         pui8  = pui8DATA(data, pDescr->offset);
 	//read index from data and write to vector
-        bitvec_write_field(vector, writeIndex, *pui8, Bits);
+	bitvec_write_field(vector, &writeIndex, *pui8, Bits);
 
 	//decode index 
         writeIndex -= Bits;
@@ -1861,7 +1861,7 @@
           }
           else
           {
-            index |= bitvec_read_field(vector, writeIndex, 1);
+	    index |= bitvec_read_field(vector, &writeIndex, 1);
           }
 
           remaining_bits_len--;
@@ -1870,7 +1870,7 @@
         }
 
         writeIndex -= Bits;
-        bitvec_write_field(vector, writeIndex, index, Bits);
+	bitvec_write_field(vector, &writeIndex, index, Bits);
 
 
         /* script index to continue on, limited in case we do not have a power of 2 */
@@ -1883,7 +1883,7 @@
           case CSN_BIT:
           {
             pui8  = pui8DATA(data, pDescr->offset);
-            bitvec_write_field(vector, writeIndex, *pui8, 1);
+	    bitvec_write_field(vector, &writeIndex, *pui8, 1);
             LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
             remaining_bits_len -= 1;
             bit_offset++;
@@ -1907,19 +1907,19 @@
               if (no_of_bits <= 8)
               {
                 pui8      = pui8DATA(data, pDescr->offset);
-                bitvec_write_field(vector, writeIndex, *pui8, no_of_bits);
+		bitvec_write_field(vector, &writeIndex, *pui8, no_of_bits);
                 LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
               }
               else if (no_of_bits <= 16)
               {
                 pui16       = pui16DATA(data, pDescr->offset);
-                bitvec_write_field(vector, writeIndex, *pui16, no_of_bits);
+		bitvec_write_field(vector, &writeIndex, *pui16, no_of_bits);
                 LOGPC(DCSN1, LOGL_NOTICE, "%s = %d | ", pDescr->sz , *pui16);
               }
               else if (no_of_bits <= 32)
               {
                 pui32       = pui32DATA(data, pDescr->offset);
-                bitvec_write_field(vector, writeIndex, *pui32, no_of_bits);
+		bitvec_write_field(vector, &writeIndex, *pui32, no_of_bits);
                 LOGPC(DCSN1, LOGL_NOTICE, "%s = %d | ", pDescr->sz , *pui32);
               }
               else
@@ -1946,19 +1946,19 @@
               if (no_of_bits <= 8)
               {
                 pui8      = pui8DATA(data, pDescr->offset);
-                bitvec_write_field(vector, writeIndex, *pui8 - (guint8)pDescr->descr.value, no_of_bits);
+		bitvec_write_field(vector, &writeIndex, *pui8 - (guint8)pDescr->descr.value, no_of_bits);
                 LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pDescr->sz , (unsigned)(*pui8 - (guint8)pDescr->descr.value));
               }
               else if (no_of_bits <= 16)
               {
                 pui16       = pui16DATA(data, pDescr->offset);
-                bitvec_write_field(vector, writeIndex, *pui16 - (guint16)pDescr->descr.value, no_of_bits);
+		bitvec_write_field(vector, &writeIndex, *pui16 - (guint16)pDescr->descr.value, no_of_bits);
                 LOGPC(DCSN1, LOGL_NOTICE, "%s = %d | ", pDescr->sz , (unsigned short)(*pui16 - (guint16)pDescr->descr.value));
               }
               else if (no_of_bits <= 32)
               {
                 pui32       = pui32DATA(data, pDescr->offset);
-                bitvec_write_field(vector, writeIndex, *pui32 - (guint16)pDescr->descr.value, no_of_bits);
+		bitvec_write_field(vector, &writeIndex, *pui32 - (guint16)pDescr->descr.value, no_of_bits);
                 LOGPC(DCSN1, LOGL_NOTICE, "%s = %d | ", pDescr->sz , (unsigned int)(*pui32 - (guint16)pDescr->descr.value));
               }
               else
@@ -1987,12 +1987,12 @@
               if (no_of_bits <= 8)
               {
                 pui8      = pui8DATA(data, pDescr->offset);
-                bitvec_write_field(vector, writeIndex, *pui8, no_of_bits);
+		bitvec_write_field(vector, &writeIndex, *pui8, no_of_bits);
                 // TODO : Change get_masked_bits8()
                 writeIndex -= no_of_bits;
                 guint8 ui8 = get_masked_bits8(vector, writeIndex, bit_offset, no_of_bits);
                 writeIndex -= no_of_bits;
-                bitvec_write_field(vector, writeIndex, ui8, no_of_bits);
+		bitvec_write_field(vector, &writeIndex, ui8, no_of_bits);
                 LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
 
               }
@@ -2030,7 +2030,7 @@
                 pui8 = pui8DATA(data, pDescr->offset);
                 do
                 {
-                  bitvec_write_field(vector, writeIndex, *pui8, no_of_bits);
+		  bitvec_write_field(vector, &writeIndex, *pui8, no_of_bits);
                   LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
                   pui8++;
                   bit_offset += no_of_bits;
@@ -2112,13 +2112,13 @@
               if (no_of_bits <= 32)
               {
                 pui32 = pui32DATA(data, pDescr->offset);
-                bitvec_write_field(vector, writeIndex, *pui32, no_of_bits);
+		bitvec_write_field(vector, &writeIndex, *pui32, no_of_bits);
                 LOGPC(DCSN1, LOGL_NOTICE, "%s = %d | ", pDescr->sz , *pui32);
               }
               else if (no_of_bits <= 64)
               {
                 pui64 = pui64DATA(data, pDescr->offset);
-                bitvec_write_field(vector, writeIndex, *pui64, no_of_bits);
+		bitvec_write_field(vector, &writeIndex, *pui64, no_of_bits);
                 LOGPC(DCSN1, LOGL_NOTICE, "%s = %lu | ", pDescr->sz , *pui64);
               }
               else
@@ -2176,7 +2176,7 @@
         unsigned exist = 0;
         pui8  = pui8DATA(data, pDescr->offset);
         exist = *pui8;
-        bitvec_write_field(vector, writeIndex, *pui8, 1);
+	bitvec_write_field(vector, &writeIndex, *pui8, 1);
         writeIndex--;
         if (CSN_EXIST_LH == pDescr->type)
         {
@@ -2184,10 +2184,10 @@
         }
         else
         {
-          fExist = bitvec_read_field(vector, writeIndex, 1);
+	  fExist = bitvec_read_field(vector, &writeIndex, 1);
         }
         writeIndex--;
-        bitvec_write_field(vector, writeIndex, fExist, 1);
+	bitvec_write_field(vector, &writeIndex, fExist, 1);
         LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pDescr->sz, (unsigned)fExist);
         pDescr++;
         remaining_bits_len -= 1;
@@ -2217,7 +2217,7 @@
           break;
         }
 
-        bitvec_write_field(vector, writeIndex, *pui8, 1);
+	bitvec_write_field(vector, &writeIndex, *pui8, 1);
         fExist = *pui8;
         LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
         remaining_bits_len -= 1;
@@ -2257,11 +2257,11 @@
         }
 
         /* the "regular" M_NEXT_EXIST_LH description element */
-        bitvec_write_field(vector, writeIndex, *pui8, 1);
+	bitvec_write_field(vector, &writeIndex, *pui8, 1);
         writeIndex--;
         fExist = get_masked_bits8(vector,writeIndex, bit_offset, 1);
         writeIndex--;
-        bitvec_write_field(vector, writeIndex, fExist, 1);
+	bitvec_write_field(vector, &writeIndex, fExist, 1);
         pui8++;
         remaining_bits_len -= 1;
 
@@ -2310,7 +2310,7 @@
 
             if (nB1 > 0)
             { /* take care of the first byte - it will be right aligned */
-              bitvec_write_field(vector, writeIndex, *pui8, nB1);
+	      bitvec_write_field(vector, &writeIndex, *pui8, nB1);
               LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
               pui8++;
               no_of_bits  -= nB1;
@@ -2320,7 +2320,7 @@
             /* remaining no_of_bits is a multiple of 8 or 0 */
             while (no_of_bits > 0)
             {
-              bitvec_write_field(vector, writeIndex, *pui8, 8);
+	      bitvec_write_field(vector, &writeIndex, *pui8, 8);
               LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
               pui8++;
               no_of_bits -= 8;
@@ -2366,14 +2366,14 @@
 
             while (no_of_bits > 0)
             {
-              bitvec_write_field(vector, writeIndex, *pui8, 8);
+	      bitvec_write_field(vector, &writeIndex, *pui8, 8);
               LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
               pui8++;
               no_of_bits -= 8;
             }
             if (nB1 > 0)
             {
-              bitvec_write_field(vector, writeIndex, *pui8, nB1);
+	      bitvec_write_field(vector, &writeIndex, *pui8, nB1);
               LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
               pui8++;
               no_of_bits  -= nB1;
@@ -2405,14 +2405,14 @@
                * < padding bits > ::= { null | 0 < spare padding > ! < Ignore : 1 bit** = < no string > > } ;
               */
               guint8 fl = filler&(0xff>>(8-bits_to_handle + 1));
-              bitvec_write_field(vector, writeIndex, fl, bits_to_handle);
+	      bitvec_write_field(vector, &writeIndex, fl, bits_to_handle);
               LOGPC(DCSN1, LOGL_NOTICE, "%u|", fl);
               remaining_bits_len -= bits_to_handle;
               bit_offset += bits_to_handle;
             }
             else if (bits_to_handle == 0)
             {
-              bitvec_write_field(vector, writeIndex, filler, 8);
+	      bitvec_write_field(vector, &writeIndex, filler, 8);
               LOGPC(DCSN1, LOGL_NOTICE, "%u|", filler);
               remaining_bits_len -= 8;
               bit_offset += 8;
@@ -2453,7 +2453,7 @@
 
           while (count > 0)
           {
-            bitvec_write_field(vector, writeIndex, *pui8, 8);
+	    bitvec_write_field(vector, &writeIndex, *pui8, 8);
             LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
             pui8++;
             bit_offset += 8;
@@ -2480,13 +2480,13 @@
         ElementCount = *pui8DATA(data, (gint16)pDescr->descr.value);
         while (ElementCount > 0)
         { /* tag control shows existence of next list elements */
-          bitvec_write_field(vector, writeIndex, Tag, 1);
+	  bitvec_write_field(vector, &writeIndex, Tag, 1);
           LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pDescr->sz , (unsigned)Tag);
           bit_offset++;
           remaining_bits_len--;
 
           /* extract and store no_of_bits long element from bitstream */
-          bitvec_write_field(vector, writeIndex, *pui8, no_of_bits);
+	  bitvec_write_field(vector, &writeIndex, *pui8, no_of_bits);
           LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pDescr->sz , (unsigned)*pui8);
           pui8++;
           remaining_bits_len -= no_of_bits;
@@ -2500,7 +2500,7 @@
           bit_offset += no_of_bits;
         }
 
-        bitvec_write_field(vector, writeIndex, !Tag, 1);
+	bitvec_write_field(vector, &writeIndex, !Tag, 1);
         LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pDescr->sz , (unsigned)(!Tag));
         bit_offset++;
         remaining_bits_len--;
@@ -2522,7 +2522,7 @@
 
         while (ElementCount > 0)
         { /* tag control shows existence of next list elements */
-          bitvec_write_field(vector, writeIndex, Tag, 1);
+	  bitvec_write_field(vector, &writeIndex, Tag, 1);
           LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pDescr->sz , (unsigned)Tag);
           bit_offset++;
 
@@ -2553,7 +2553,7 @@
           }
         }
 
-        bitvec_write_field(vector, writeIndex, !Tag, 1);
+	bitvec_write_field(vector, &writeIndex, !Tag, 1);
         LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pDescr->sz , (unsigned)(!Tag));
         bit_offset++;
 
@@ -2591,7 +2591,7 @@
         { /* get data element */
           if (ElementCount != ElementNum)
           {
-            bitvec_write_field(vector, writeIndex, Tag, 1);
+	    bitvec_write_field(vector, &writeIndex, Tag, 1);
             LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pDescr->sz , (unsigned)Tag);
             bit_offset++;
             remaining_bits_len--;
@@ -2618,7 +2618,7 @@
           }
 
         }
-        bitvec_write_field(vector, writeIndex, !Tag, 1);
+	bitvec_write_field(vector, &writeIndex, !Tag, 1);
         bit_offset++;
         remaining_bits_len--;
         Tag = STANDARD_TAG; /* in case it was set to "reversed" */
@@ -2629,7 +2629,7 @@
       case CSN_FIXED:
       { /* Verify the fixed bits */
         guint8  no_of_bits = (guint8) pDescr->i;
-        bitvec_write_field(vector, writeIndex, pDescr->offset, no_of_bits);
+	bitvec_write_field(vector, &writeIndex, pDescr->offset, no_of_bits);
         LOGPC(DCSN1, LOGL_NOTICE, "%s = %u | ", pDescr->sz , (unsigned)pDescr->offset);
         remaining_bits_len   -= no_of_bits;
         bit_offset += no_of_bits;
diff --git a/src/csn1.h b/src/csn1.h
index 96f7558..3f5b849 100644
--- a/src/csn1.h
+++ b/src/csn1.h
@@ -25,7 +25,10 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
-#include <bitvector.h>
+extern "C" {
+#include <osmocom/core/bitvec.h>
+}
+
 #include <iostream>
 #include <cstdlib>
 #ifndef _PACKET_CSN1_H_
diff --git a/src/egprs_rlc_compression.cpp b/src/egprs_rlc_compression.cpp
index 82605ff..7eeb7d2 100644
--- a/src/egprs_rlc_compression.cpp
+++ b/src/egprs_rlc_compression.cpp
@@ -528,10 +528,10 @@
 		/* put run length of Ones in uncompressed bitmap */
 		while (run_length != 0) {
 			if (run_length > 8) {
-				bitvec_write_field(dest, wp, data, 8);
+				bitvec_write_field(dest, &wp, data, 8);
 				run_length = run_length - 8;
 			} else {
-				bitvec_write_field(dest, wp, data, run_length);
+				bitvec_write_field(dest, &wp, data, run_length);
 				run_length = 0;
 			}
 		}
@@ -581,7 +581,7 @@
 		*codewrd_bitmap = t4_term[start][*run_len_cnt];
 		*codewrd_len = t4_term_length[start][*run_len_cnt];
 	}
-	bitvec_write_field(crbb_vec, writeIndex, *codewrd_bitmap, *codewrd_len);
+	bitvec_write_field(crbb_vec, &writeIndex, *codewrd_bitmap, *codewrd_len);
 }
 
 /* Compress received block bitmap */
diff --git a/src/encoding.cpp b/src/encoding.cpp
index ea38b77..ed8fdaa 100644
--- a/src/encoding.cpp
+++ b/src/encoding.cpp
@@ -40,12 +40,12 @@
 static inline bool write_tai(bitvec *dest, unsigned& wp, int8_t tai)
 {
 	if (tai < 0) { /* No TIMING_ADVANCE_INDEX: */
-		bitvec_write_field(dest, wp, 0, 1);
+		bitvec_write_field(dest, &wp, 0, 1);
 		return false;
 	}
 	/* TIMING_ADVANCE_INDEX: */
-	bitvec_write_field(dest, wp, 1, 1);
-	bitvec_write_field(dest, wp, tai, 4);
+	bitvec_write_field(dest, &wp, 1, 1);
+	bitvec_write_field(dest, &wp, tai, 4);
 	return true;
 }
 
@@ -53,10 +53,10 @@
 static inline void write_ta(bitvec *dest, unsigned& wp, int8_t ta)
 {
 	if (ta < 0) /* No TIMING_ADVANCE_VALUE: */
-		bitvec_write_field(dest, wp, 0, 1);
+		bitvec_write_field(dest, &wp, 0, 1);
 	else { /* TIMING_ADVANCE_VALUE: */
-		bitvec_write_field(dest, wp, 1, 1);
-		bitvec_write_field(dest, wp, ta, 6);
+		bitvec_write_field(dest, &wp, 1, 1);
+		bitvec_write_field(dest, &wp, ta, 6);
 	}
 }
 
@@ -70,7 +70,7 @@
 {
 	write_ta(dest, wp, ta);
 	if (write_tai(dest, wp, tai)) /* TIMING_ADVANCE_TIMESLOT_NUMBER: */
-		bitvec_write_field(dest, wp, ts, 3);
+		bitvec_write_field(dest, &wp, ts, 3);
 }
 
 static int write_ia_rest_downlink(
@@ -85,40 +85,40 @@
 		return -EINVAL;
 	}
 	// GSM 04.08 10.5.2.16 IA Rest Octets
-	bitvec_write_field_lh(dest, wp, 3, 2);   // "HH"
-	bitvec_write_field(dest, wp, 1, 2);   // "01" Packet Downlink Assignment
-	bitvec_write_field(dest, wp,tbf->tlli(),32); // TLLI
-	bitvec_write_field(dest, wp,0x1,1);   // switch TFI   : on
-	bitvec_write_field(dest, wp,tbf->tfi(),5);   // TFI
-	bitvec_write_field(dest, wp,0x0,1);   // RLC acknowledged mode
+	bitvec_write_field(dest, &wp, 3, 2);   // "HH"
+	bitvec_write_field(dest, &wp, 1, 2);   // "01" Packet Downlink Assignment
+	bitvec_write_field(dest, &wp,tbf->tlli(),32); // TLLI
+	bitvec_write_field(dest, &wp,0x1,1);   // switch TFI   : on
+	bitvec_write_field(dest, &wp,tbf->tfi(),5);   // TFI
+	bitvec_write_field(dest, &wp,0x0,1);   // RLC acknowledged mode
 	if (alpha) {
-		bitvec_write_field(dest, wp,0x1,1);   // ALPHA = present
-		bitvec_write_field(dest, wp,alpha,4);   // ALPHA
+		bitvec_write_field(dest, &wp,0x1,1);   // ALPHA = present
+		bitvec_write_field(dest, &wp,alpha,4);   // ALPHA
 	} else {
-		bitvec_write_field(dest, wp,0x0,1);   // ALPHA = not present
+		bitvec_write_field(dest, &wp,0x0,1);   // ALPHA = not present
 	}
-	bitvec_write_field(dest, wp,gamma,5);   // GAMMA power control parameter
-	bitvec_write_field(dest, wp,polling,1);   // Polling Bit
-	bitvec_write_field(dest, wp, ta_valid, 1); // N. B: NOT related to TAI!
+	bitvec_write_field(dest, &wp,gamma,5);   // GAMMA power control parameter
+	bitvec_write_field(dest, &wp,polling,1);   // Polling Bit
+	bitvec_write_field(dest, &wp, ta_valid, 1); // N. B: NOT related to TAI!
 	write_tai(dest, wp, ta_idx);
 	if (polling) {
-		bitvec_write_field(dest, wp,0x1,1);   // TBF Starting TIME present
-		bitvec_write_field(dest, wp,(fn / (26 * 51)) % 32,5); // T1'
-		bitvec_write_field(dest, wp,fn % 51,6);               // T3
-		bitvec_write_field(dest, wp,fn % 26,5);               // T2
+		bitvec_write_field(dest, &wp,0x1,1);   // TBF Starting TIME present
+		bitvec_write_field(dest, &wp,(fn / (26 * 51)) % 32,5); // T1'
+		bitvec_write_field(dest, &wp,fn % 51,6);               // T3
+		bitvec_write_field(dest, &wp,fn % 26,5);               // T2
 	} else {
-		bitvec_write_field(dest, wp,0x0,1);   // TBF Starting TIME present
+		bitvec_write_field(dest, &wp,0x0,1);   // TBF Starting TIME present
 	}
-	bitvec_write_field(dest, wp,0x0,1);   // P0 not present
-	//		bitvec_write_field(dest, wp,0x1,1);   // P0 not present
-	//		bitvec_write_field(dest, wp,0xb,4);
+	bitvec_write_field(dest, &wp,0x0,1);   // P0 not present
+	//		bitvec_write_field(dest, &wp,0x1,1);   // P0 not present
+	//		bitvec_write_field(dest, &wp,,0xb,4);
 	if (tbf->is_egprs_enabled()) {
 		/* see GMS 44.018, 10.5.2.16 */
 		unsigned int ws_enc = (tbf->m_window.ws() - 64) / 32;
-		bitvec_write_field_lh(dest, wp, 1, 1);  // "H"
-		bitvec_write_field(dest, wp, ws_enc,5); // EGPRS Window Size
-		bitvec_write_field(dest, wp, 0x0,2);    // LINK_QUALITY_MEASUREMENT_MODE
-		bitvec_write_field(dest, wp, 0,1);      // BEP_PERIOD2 not present
+		bitvec_write_field(dest, &wp, 1, 1);  // "H"
+		bitvec_write_field(dest, &wp, ws_enc, 5); // EGPRS Window Size
+		bitvec_write_field(dest, &wp, 0x0, 2);    // LINK_QUALITY_MEASUREMENT_MODE
+		bitvec_write_field(dest, &wp, 0, 1);      // BEP_PERIOD2 not present
 	}
 
 	return 0;
@@ -133,40 +133,40 @@
 	OSMO_ASSERT(!tbf || !tbf->is_egprs_enabled());
 
 	// GMS 04.08 10.5.2.37b 10.5.2.16
-	bitvec_write_field_lh(dest, wp, 3, 2);    // "HH"
-	bitvec_write_field(dest, wp, 0, 2);    // "0" Packet Uplink Assignment
+	bitvec_write_field(dest, &wp, 3, 2);    // "HH"
+	bitvec_write_field(dest, &wp, 0, 2);    // "0" Packet Uplink Assignment
 	if (tbf == NULL) {
-		bitvec_write_field(dest, wp, 0, 1);    // Block Allocation : Single Block Allocation
+		bitvec_write_field(dest, &wp, 0, 1);    // Block Allocation : Single Block Allocation
 		if (alpha) {
-			bitvec_write_field(dest, wp,0x1,1);   // ALPHA = present
-			bitvec_write_field(dest, wp,alpha,4);   // ALPHA = present
+			bitvec_write_field(dest, &wp,0x1,1);   // ALPHA = present
+			bitvec_write_field(dest, &wp,alpha,4);   // ALPHA = present
 		} else
-			bitvec_write_field(dest, wp,0x0,1);   // ALPHA = not present
-		bitvec_write_field(dest, wp,gamma,5);   // GAMMA power control parameter
+			bitvec_write_field(dest, &wp,0x0,1);   // ALPHA = not present
+		bitvec_write_field(dest, &wp,gamma,5);   // GAMMA power control parameter
 		write_tai(dest, wp, ta_idx);
-		bitvec_write_field(dest, wp, 1, 1);    // TBF_STARTING_TIME_FLAG
-		bitvec_write_field(dest, wp,(fn / (26 * 51)) % 32,5); // T1'
-		bitvec_write_field(dest, wp,fn % 51,6);               // T3
-		bitvec_write_field(dest, wp,fn % 26,5);               // T2
+		bitvec_write_field(dest, &wp, 1, 1);    // TBF_STARTING_TIME_FLAG
+		bitvec_write_field(dest, &wp,(fn / (26 * 51)) % 32,5); // T1'
+		bitvec_write_field(dest, &wp,fn % 51,6);               // T3
+		bitvec_write_field(dest, &wp,fn % 26,5);               // T2
 	} else {
-		bitvec_write_field(dest, wp, 1, 1);    // Block Allocation : Not Single Block Allocation
-		bitvec_write_field(dest, wp, tbf->tfi(), 5);  // TFI_ASSIGNMENT Temporary Flow Identity
-		bitvec_write_field(dest, wp, 0, 1);    // POLLING
-		bitvec_write_field(dest, wp, 0, 1);    // ALLOCATION_TYPE: dynamic
-		bitvec_write_field(dest, wp, usf, 3);    // USF
-		bitvec_write_field(dest, wp, 0, 1);    // USF_GRANULARITY
-		bitvec_write_field(dest, wp, 0, 1);   // "0" power control: Not Present
-		bitvec_write_field(dest, wp, tbf->current_cs().to_num()-1, 2);    // CHANNEL_CODING_COMMAND 
-		bitvec_write_field(dest, wp, 1, 1);    // TLLI_BLOCK_CHANNEL_CODING
+		bitvec_write_field(dest, &wp, 1, 1);    // Block Allocation : Not Single Block Allocation
+		bitvec_write_field(dest, &wp, tbf->tfi(), 5);  // TFI_ASSIGNMENT Temporary Flow Identity
+		bitvec_write_field(dest, &wp, 0, 1);    // POLLING
+		bitvec_write_field(dest, &wp, 0, 1);    // ALLOCATION_TYPE: dynamic
+		bitvec_write_field(dest, &wp, usf, 3);    // USF
+		bitvec_write_field(dest, &wp, 0, 1);    // USF_GRANULARITY
+		bitvec_write_field(dest, &wp, 0, 1);   // "0" power control: Not Present
+		bitvec_write_field(dest, &wp, tbf->current_cs().to_num()-1, 2);    // CHANNEL_CODING_COMMAND
+		bitvec_write_field(dest, &wp, 1, 1);    // TLLI_BLOCK_CHANNEL_CODING
 		if (alpha) {
-			bitvec_write_field(dest, wp,0x1,1);   // ALPHA = present
-			bitvec_write_field(dest, wp,alpha,4);   // ALPHA
+			bitvec_write_field(dest, &wp,0x1,1);   // ALPHA = present
+			bitvec_write_field(dest, &wp,alpha,4);   // ALPHA
 		} else
-			bitvec_write_field(dest, wp,0x0,1);   // ALPHA = not present
-		bitvec_write_field(dest, wp,gamma,5);   // GAMMA power control parameter
+			bitvec_write_field(dest, &wp,0x0,1);   // ALPHA = not present
+		bitvec_write_field(dest, &wp,gamma,5);   // GAMMA power control parameter
 		/* note: there is no choise for TAI and no starting time */
-		bitvec_write_field(dest, wp, 0, 1);   // switch TIMING_ADVANCE_INDEX = off
-		bitvec_write_field(dest, wp, 0, 1);    // TBF_STARTING_TIME_FLAG
+		bitvec_write_field(dest, &wp, 0, 1);   // switch TIMING_ADVANCE_INDEX = off
+		bitvec_write_field(dest, &wp, 0, 1);    // TBF_STARTING_TIME_FLAG
 	}
 	return 0;
 }
@@ -183,60 +183,60 @@
 
 	extended_ra = (ra & 0x1F);
 
-	bitvec_write_field(dest, wp, 1, 2);    /* LH */
-	bitvec_write_field(dest, wp, 0, 2);    /* 0 EGPRS Uplink Assignment */
-	bitvec_write_field(dest, wp, extended_ra, 5);    /* Extended RA */
-	bitvec_write_field(dest, wp, 0, 1);    /* Access technology Request */
+	bitvec_write_field(dest, &wp, 1, 2);    /* LH */
+	bitvec_write_field(dest, &wp, 0, 2);    /* 0 EGPRS Uplink Assignment */
+	bitvec_write_field(dest, &wp, extended_ra, 5);    /* Extended RA */
+	bitvec_write_field(dest, &wp, 0, 1);    /* Access technology Request */
 
 	if (tbf == NULL) {
 
-		bitvec_write_field(dest, wp, 0, 1); /* multiblock allocation */
+		bitvec_write_field(dest, &wp, 0, 1); /* multiblock allocation */
 
 		if (alpha) {
-			bitvec_write_field(dest, wp, 0x1, 1); /* ALPHA =yes */
-			bitvec_write_field(dest, wp, alpha, 4); /* ALPHA */
+			bitvec_write_field(dest, &wp, 0x1, 1); /* ALPHA =yes */
+			bitvec_write_field(dest, &wp, alpha, 4); /* ALPHA */
 		} else {
-			bitvec_write_field(dest, wp, 0x0, 1); /* ALPHA = no */
+			bitvec_write_field(dest, &wp, 0x0, 1); /* ALPHA = no */
 		}
 
-		bitvec_write_field(dest, wp, gamma, 5); /* GAMMA power contrl */
-		bitvec_write_field(dest, wp, (fn / (26 * 51)) % 32, 5);/* T1' */
-		bitvec_write_field(dest, wp, fn % 51, 6);              /* T3 */
-		bitvec_write_field(dest, wp, fn % 26, 5);              /* T2 */
-		bitvec_write_field(dest, wp, 0, 2); /* Radio block allocation */
+		bitvec_write_field(dest, &wp, gamma, 5); /* GAMMA power contrl */
+		bitvec_write_field(dest, &wp, (fn / (26 * 51)) % 32, 5);/* T1' */
+		bitvec_write_field(dest, &wp, fn % 51, 6);              /* T3 */
+		bitvec_write_field(dest, &wp, fn % 26, 5);              /* T2 */
+		bitvec_write_field(dest, &wp, 0, 2); /* Radio block allocation */
 
-		bitvec_write_field(dest, wp, 0, 1);
+		bitvec_write_field(dest, &wp, 0, 1);
 
 	} else {
 
 		ws_enc = (tbf->m_window.ws() - 64) / 32;
 
-		bitvec_write_field(dest, wp, 1, 1);     /* single block alloc */
-		bitvec_write_field(dest, wp, tbf->tfi(), 5);/* TFI assignment */
-		bitvec_write_field(dest, wp, 0, 1);     /* polling bit */
-		bitvec_write_field(dest, wp, 0, 1);     /* constant */
-		bitvec_write_field(dest, wp, usf, 3);   /* USF bit */
-		bitvec_write_field(dest, wp, 0, 1);     /* USF granularity */
-		bitvec_write_field(dest, wp, 0, 1);     /* P0 */
+		bitvec_write_field(dest, &wp, 1, 1);     /* single block alloc */
+		bitvec_write_field(dest, &wp, tbf->tfi(), 5);/* TFI assignment */
+		bitvec_write_field(dest, &wp, 0, 1);     /* polling bit */
+		bitvec_write_field(dest, &wp, 0, 1);     /* constant */
+		bitvec_write_field(dest, &wp, usf, 3);   /* USF bit */
+		bitvec_write_field(dest, &wp, 0, 1);     /* USF granularity */
+		bitvec_write_field(dest, &wp, 0, 1);     /* P0 */
 		/* MCS */
-		bitvec_write_field(dest, wp, tbf->current_cs().to_num()-1, 4);
+		bitvec_write_field(dest, &wp, tbf->current_cs().to_num()-1, 4);
 		/* tlli channel block */
-		bitvec_write_field(dest, wp, tbf->tlli(), 1);
-		bitvec_write_field(dest, wp, 0, 1);   /* BEP period present */
-		bitvec_write_field(dest, wp, 0, 1);   /* resegmentation */
-		bitvec_write_field(dest, wp, ws_enc, 5);/* egprs window_size */
+		bitvec_write_field(dest, &wp, tbf->tlli(), 1);
+		bitvec_write_field(dest, &wp, 0, 1);   /* BEP period present */
+		bitvec_write_field(dest, &wp, 0, 1);   /* resegmentation */
+		bitvec_write_field(dest, &wp, ws_enc, 5);/* egprs window_size */
 
 		if (alpha) {
-			bitvec_write_field(dest, wp, 0x1, 1);   /* ALPHA =yes */
-			bitvec_write_field(dest, wp, alpha, 4); /* ALPHA */
+			bitvec_write_field(dest, &wp, 0x1, 1);   /* ALPHA =yes */
+			bitvec_write_field(dest, &wp, alpha, 4); /* ALPHA */
 		} else {
-			bitvec_write_field(dest, wp, 0x0, 1);   /* ALPHA = no */
+			bitvec_write_field(dest, &wp, 0x0, 1);   /* ALPHA = no */
 		}
 
-		bitvec_write_field(dest, wp, gamma, 5); /* GAMMA power contrl */
-		bitvec_write_field(dest, wp, 0, 1); /* TIMING_ADVANCE_INDEX */
-		bitvec_write_field(dest, wp, 0, 1); /* TBF_STARTING_TIME_FLAG */
-		bitvec_write_field(dest, wp, 0, 1); /* NULL */
+		bitvec_write_field(dest, &wp, gamma, 5); /* GAMMA power contrl */
+		bitvec_write_field(dest, &wp, 0, 1); /* TIMING_ADVANCE_INDEX */
+		bitvec_write_field(dest, &wp, 0, 1); /* TBF_STARTING_TIME_FLAG */
+		bitvec_write_field(dest, &wp, 0, 1); /* NULL */
 	}
 
 	return 0;
@@ -255,17 +255,17 @@
 	int plen;
 	int i;
 
-	bitvec_write_field(dest, wp, 0x0, 4);  // Skip Indicator
-	bitvec_write_field(dest, wp, 0x6, 4);  // Protocol Discriminator
-	bitvec_write_field(dest, wp, 0x3A, 8); // Immediate Assign Message Type
+	bitvec_write_field(dest, &wp, 0x0, 4);  // Skip Indicator
+	bitvec_write_field(dest, &wp, 0x6, 4);  // Protocol Discriminator
+	bitvec_write_field(dest, &wp, 0x3A, 8); // Immediate Assign Message Type
 
 	// feature indicator
-	bitvec_write_field(dest, wp, 0x0, 1);      // spare
-	bitvec_write_field(dest, wp, 0x0, 1);      // spare
-	bitvec_write_field(dest, wp, 0x0, 1);      // no cs
-	bitvec_write_field(dest, wp, 0x1, 1);      // implicit detach for PS
+	bitvec_write_field(dest, &wp, 0x0, 1);      // spare
+	bitvec_write_field(dest, &wp, 0x0, 1);      // spare
+	bitvec_write_field(dest, &wp, 0x0, 1);      // no cs
+	bitvec_write_field(dest, &wp, 0x1, 1);      // implicit detach for PS
 
-	bitvec_write_field(dest, wp, 0x0, 4); // Page Mode
+	bitvec_write_field(dest, &wp, 0x0, 4); // Page Mode
 	/*
 	 * 9.1.20.2 of 44.018 version 11.7.0 Release 11
 	 * Filling of the message
@@ -279,18 +279,18 @@
 		if (((burst_type == GSM_L1_BURST_TYPE_ACCESS_1) ||
 			(burst_type == GSM_L1_BURST_TYPE_ACCESS_2))) {
 			//9.1.20.2a of 44.018 version 11.7.0 Release 11
-			bitvec_write_field(dest, wp, 0x7f, 8);  /* RACH value */
+			bitvec_write_field(dest, &wp, 0x7f, 8);  /* RACH value */
 		} else {
-			bitvec_write_field(dest, wp, ra, 8);	/* RACH value */
+			bitvec_write_field(dest, &wp, ra, 8);	/* RACH value */
 		}
 
-		bitvec_write_field(dest, wp,
+		bitvec_write_field(dest, &wp,
 					(ref_fn / (26 * 51)) % 32, 5); // T1'
-		bitvec_write_field(dest, wp, ref_fn % 51, 6);          // T3
-		bitvec_write_field(dest, wp, ref_fn % 26, 5);          // T2
+		bitvec_write_field(dest, &wp, ref_fn % 51, 6);          // T3
+		bitvec_write_field(dest, &wp, ref_fn % 26, 5);          // T2
 
 		/* TODO: Make it configurable */
-		bitvec_write_field(dest, wp, 20, 8); //Wait Indication 1
+		bitvec_write_field(dest, &wp, 20, 8); //Wait Indication 1
 	}
 
 	plen = wp / 8;
@@ -308,14 +308,14 @@
 		uint8_t extended_ra = 0;
 
 		extended_ra = (ra & 0x1F);
-		bitvec_write_field(dest, wp, 0x1, 1);
-		bitvec_write_field(dest, wp, extended_ra, 5); /* Extended RA */
+		bitvec_write_field(dest, &wp, 0x1, 1);
+		bitvec_write_field(dest, &wp, extended_ra, 5); /* Extended RA */
 	} else {
-		bitvec_write_field(dest, wp, 0x0, 1);
+		bitvec_write_field(dest, &wp, 0x0, 1);
 	}
-	bitvec_write_field(dest, wp, 0x0, 1);
-	bitvec_write_field(dest, wp, 0x0, 1);
-	bitvec_write_field(dest, wp, 0x0, 1);
+	bitvec_write_field(dest, &wp, 0x0, 1);
+	bitvec_write_field(dest, &wp, 0x0, 1);
+	bitvec_write_field(dest, &wp, 0x0, 1);
 
 	return plen;
 }
@@ -335,44 +335,44 @@
 	int plen;
 	int rc;
 
-	bitvec_write_field(dest, wp,0x0,4);  // Skip Indicator
-	bitvec_write_field(dest, wp,0x6,4);  // Protocol Discriminator
-	bitvec_write_field(dest, wp,0x3F,8); // Immediate Assignment Message Type
+	bitvec_write_field(dest, &wp,0x0,4);  // Skip Indicator
+	bitvec_write_field(dest, &wp,0x6,4);  // Protocol Discriminator
+	bitvec_write_field(dest, &wp,0x3F,8); // Immediate Assignment Message Type
 
 	// 10.5.2.25b Dedicated mode or TBF
-	bitvec_write_field(dest, wp,0x0,1);      // spare
-	bitvec_write_field(dest, wp,0x0,1);      // TMA : Two-message assignment: No meaning
-	bitvec_write_field(dest, wp,downlink,1); // Downlink : Downlink assignment to mobile in packet idle mode
-	bitvec_write_field(dest, wp,0x1,1);      // T/D : TBF or dedicated mode: this message assigns a Temporary Block Flow (TBF).
+	bitvec_write_field(dest, &wp,0x0,1);      // spare
+	bitvec_write_field(dest, &wp,0x0,1);      // TMA : Two-message assignment: No meaning
+	bitvec_write_field(dest, &wp,downlink,1); // Downlink : Downlink assignment to mobile in packet idle mode
+	bitvec_write_field(dest, &wp,0x1,1);      // T/D : TBF or dedicated mode: this message assigns a Temporary Block Flow (TBF).
 
-	bitvec_write_field(dest, wp,0x0,4); // Page Mode
+	bitvec_write_field(dest, &wp,0x0,4); // Page Mode
 
 	// GSM 04.08 10.5.2.25a Packet Channel Description
-	bitvec_write_field(dest, wp,0x1,5);                               // Channel type
-	bitvec_write_field(dest, wp,ts,3);     // TN
-	bitvec_write_field(dest, wp,tsc,3);    // TSC
-	bitvec_write_field(dest, wp,0x0,3);                               // non-hopping RF channel configuraion
-	bitvec_write_field(dest, wp,arfcn,10); // ARFCN
+	bitvec_write_field(dest, &wp,0x1,5);                               // Channel type
+	bitvec_write_field(dest, &wp,ts,3);     // TN
+	bitvec_write_field(dest, &wp,tsc,3);    // TSC
+	bitvec_write_field(dest, &wp,0x0,3);                               // non-hopping RF channel configuraion
+	bitvec_write_field(dest, &wp,arfcn,10); // ARFCN
 
 	//10.5.2.30 Request Reference
 	if (((burst_type == GSM_L1_BURST_TYPE_ACCESS_1) ||
 		(burst_type == GSM_L1_BURST_TYPE_ACCESS_2))) {
-		bitvec_write_field(dest, wp, 0x7f, 8);  /* RACH value */
+		bitvec_write_field(dest, &wp, 0x7f, 8);  /* RACH value */
 	} else {
-		bitvec_write_field(dest, wp, ra, 8);	/* RACH value */
+		bitvec_write_field(dest, &wp, ra, 8);	/* RACH value */
 	}
 
-	bitvec_write_field(dest, wp,(ref_fn / (26 * 51)) % 32,5); // T1'
-	bitvec_write_field(dest, wp,ref_fn % 51,6);               // T3
-	bitvec_write_field(dest, wp,ref_fn % 26,5);               // T2
+	bitvec_write_field(dest, &wp,(ref_fn / (26 * 51)) % 32,5); // T1'
+	bitvec_write_field(dest, &wp,ref_fn % 51,6);               // T3
+	bitvec_write_field(dest, &wp,ref_fn % 26,5);               // T2
 
 	// 10.5.2.40 Timing Advance
-	bitvec_write_field(dest, wp,0x0,2); // spare
-	bitvec_write_field(dest, wp,ta,6);  // Timing Advance value
+	bitvec_write_field(dest, &wp,0x0,2); // spare
+	bitvec_write_field(dest, &wp,ta,6);  // Timing Advance value
 
 	// No mobile allocation in non-hopping systems.
 	// A zero-length LV.  Just write L=0.
-	bitvec_write_field(dest, wp,0,8);
+	bitvec_write_field(dest, &wp,0,8);
 
 	if ((wp % 8)) {
 		LOGP(DRLCMACUL, LOGL_ERROR, "Length of IMM.ASS without rest "
@@ -420,83 +420,83 @@
 	/* timeslot assigned for the Continuous Timing Advance procedure */
 	uint8_t ta_ts = 0; /* FIXME: supply it as parameter from caller */
 
-	bitvec_write_field(dest, wp,0x1,2);  // Payload Type
-	bitvec_write_field(dest, wp,0x0,2);  // Uplink block with TDMA framenumber (N+13)
-	bitvec_write_field(dest, wp,poll,1);  // Suppl/Polling Bit
-	bitvec_write_field(dest, wp,0x0,3);  // Uplink state flag
-	bitvec_write_field(dest, wp,0xa,6);  // MESSAGE TYPE
+	bitvec_write_field(dest, &wp,0x1,2);  // Payload Type
+	bitvec_write_field(dest, &wp,0x0,2);  // Uplink block with TDMA framenumber (N+13)
+	bitvec_write_field(dest, &wp,poll,1);  // Suppl/Polling Bit
+	bitvec_write_field(dest, &wp,0x0,3);  // Uplink state flag
+	bitvec_write_field(dest, &wp,0xa,6);  // MESSAGE TYPE
 
-	bitvec_write_field(dest, wp,0x0,2);  // Page Mode
+	bitvec_write_field(dest, &wp,0x0,2);  // Page Mode
 
-	bitvec_write_field(dest, wp,0x0,1); // switch PERSIST_LEVEL: off
+	bitvec_write_field(dest, &wp,0x0,1); // switch PERSIST_LEVEL: off
 	if (use_tlli) {
-		bitvec_write_field(dest, wp,0x2,2); // switch TLLI   : on
-		bitvec_write_field(dest, wp,tlli,32); // TLLI
+		bitvec_write_field(dest, &wp,0x2,2); // switch TLLI   : on
+		bitvec_write_field(dest, &wp,tlli,32); // TLLI
 	} else {
-		bitvec_write_field(dest, wp,0x0,1); // switch TFI : on
-		bitvec_write_field(dest, wp,old_downlink,1); // 0=UPLINK TFI, 1=DL TFI
-		bitvec_write_field(dest, wp,old_tfi,5); // TFI
+		bitvec_write_field(dest, &wp,0x0,1); // switch TFI : on
+		bitvec_write_field(dest, &wp,old_downlink,1); // 0=UPLINK TFI, 1=DL TFI
+		bitvec_write_field(dest, &wp,old_tfi,5); // TFI
 	}
 
 	if (!use_egprs) {
-		bitvec_write_field(dest, wp,0x0,1); // Message escape
-		bitvec_write_field(dest, wp,tbf->current_cs().to_num()-1, 2); // CHANNEL_CODING_COMMAND 
-		bitvec_write_field(dest, wp,0x1,1); // TLLI_BLOCK_CHANNEL_CODING 
+		bitvec_write_field(dest, &wp,0x0,1); // Message escape
+		bitvec_write_field(dest, &wp,tbf->current_cs().to_num()-1, 2); // CHANNEL_CODING_COMMAND
+		bitvec_write_field(dest, &wp,0x1,1); // TLLI_BLOCK_CHANNEL_CODING
 		write_ta_ie(dest, wp,tbf->ta(), ta_idx, ta_ts);
 	} else { /* EPGRS */
 		unsigned int ws_enc = (tbf->m_window.ws() - 64) / 32;
-		bitvec_write_field(dest, wp,0x1,1); // Message escape
-		bitvec_write_field(dest, wp,0x0,2); // EGPRS message contents
-		bitvec_write_field(dest, wp,0x0,1); // No CONTENTION_RESOLUTION_TLLI
-		bitvec_write_field(dest, wp,0x0,1); // No COMPACT reduced MA
-		bitvec_write_field(dest, wp,tbf->current_cs().to_num()-1, 4); // EGPRS Modulation and Coding IE
+		bitvec_write_field(dest, &wp,0x1,1); // Message escape
+		bitvec_write_field(dest, &wp,0x0,2); // EGPRS message contents
+		bitvec_write_field(dest, &wp,0x0,1); // No CONTENTION_RESOLUTION_TLLI
+		bitvec_write_field(dest, &wp,0x0,1); // No COMPACT reduced MA
+		bitvec_write_field(dest, &wp,tbf->current_cs().to_num()-1, 4); // EGPRS Modulation and Coding IE
 		/* 0: no RESEGMENT, 1: Segmentation*/
-		bitvec_write_field(dest, wp, 0x1, 1);
-		bitvec_write_field(dest, wp,ws_enc,5); // EGPRS Window Size
-		bitvec_write_field(dest, wp,0x0,1); // No Access Technologies Request
-		bitvec_write_field(dest, wp,0x0,1); // No ARAC RETRANSMISSION REQUEST
-		bitvec_write_field(dest, wp,0x1,1); // TLLI_BLOCK_CHANNEL_CODING 
-		bitvec_write_field(dest, wp,0x0,1); // No BEP_PERIOD2
+		bitvec_write_field(dest, &wp, 0x1, 1);
+		bitvec_write_field(dest, &wp,ws_enc,5); // EGPRS Window Size
+		bitvec_write_field(dest, &wp,0x0,1); // No Access Technologies Request
+		bitvec_write_field(dest, &wp,0x0,1); // No ARAC RETRANSMISSION REQUEST
+		bitvec_write_field(dest, &wp,0x1,1); // TLLI_BLOCK_CHANNEL_CODING
+		bitvec_write_field(dest, &wp,0x0,1); // No BEP_PERIOD2
 		write_ta_ie(dest, wp,tbf->ta(), ta_idx, ta_ts);
-		bitvec_write_field(dest, wp,0x0,1); // No Packet Extended Timing Advance
+		bitvec_write_field(dest, &wp,0x0,1); // No Packet Extended Timing Advance
 	}
 
 #if 1
-	bitvec_write_field(dest, wp,0x1,1); // Frequency Parameters information elements = present
-	bitvec_write_field(dest, wp,tbf->tsc(),3); // Training Sequence Code (TSC)
-	bitvec_write_field(dest, wp,0x0,2); // ARFCN = present
-	bitvec_write_field(dest, wp,tbf->trx->arfcn,10); // ARFCN
+	bitvec_write_field(dest, &wp,0x1,1); // Frequency Parameters information elements = present
+	bitvec_write_field(dest, &wp,tbf->tsc(),3); // Training Sequence Code (TSC)
+	bitvec_write_field(dest, &wp,0x0,2); // ARFCN = present
+	bitvec_write_field(dest, &wp,tbf->trx->arfcn,10); // ARFCN
 #else
-	bitvec_write_field(dest, wp,0x0,1); // Frequency Parameters = off
+	bitvec_write_field(dest, &wp,0x0,1); // Frequency Parameters = off
 #endif
 
-	bitvec_write_field(dest, wp,0x1,2); // Dynamic Allocation
+	bitvec_write_field(dest, &wp,0x1,2); // Dynamic Allocation
 
-	bitvec_write_field(dest, wp,0x0,1); // Extended Dynamic Allocation = off
-	bitvec_write_field(dest, wp,0x0,1); // P0 = off
+	bitvec_write_field(dest, &wp,0x0,1); // Extended Dynamic Allocation = off
+	bitvec_write_field(dest, &wp,0x0,1); // P0 = off
 
-	bitvec_write_field(dest, wp,0x0,1); // USF_GRANULARITY
-	bitvec_write_field(dest, wp,0x1,1); // switch TFI   : on
-	bitvec_write_field(dest, wp,tbf->tfi(),5);// TFI
+	bitvec_write_field(dest, &wp,0x0,1); // USF_GRANULARITY
+	bitvec_write_field(dest, &wp,0x1,1); // switch TFI   : on
+	bitvec_write_field(dest, &wp,tbf->tfi(),5);// TFI
 
-	bitvec_write_field(dest, wp,0x0,1); //
-	bitvec_write_field(dest, wp,0x0,1); // TBF Starting Time = off
+	bitvec_write_field(dest, &wp,0x0,1); //
+	bitvec_write_field(dest, &wp,0x0,1); // TBF Starting Time = off
 	if (alpha || gamma) {
-		bitvec_write_field(dest, wp,0x1,1); // Timeslot Allocation with Power Control
-		bitvec_write_field(dest, wp,alpha,4);   // ALPHA
+		bitvec_write_field(dest, &wp,0x1,1); // Timeslot Allocation with Power Control
+		bitvec_write_field(dest, &wp,alpha,4);   // ALPHA
 	} else
-		bitvec_write_field(dest, wp,0x0,1); // Timeslot Allocation
+		bitvec_write_field(dest, &wp,0x0,1); // Timeslot Allocation
 
 	for (ts = 0; ts < 8; ts++) {
 		if (tbf->pdch[ts]) {
-			bitvec_write_field(dest, wp,0x1,1); // USF_TN(i): on
-			bitvec_write_field(dest, wp,tbf->m_usf[ts],3); // USF_TN(i)
+			bitvec_write_field(dest, &wp,0x1,1); // USF_TN(i): on
+			bitvec_write_field(dest, &wp,tbf->m_usf[ts],3); // USF_TN(i)
 			if (alpha || gamma)
-				bitvec_write_field(dest, wp,gamma,5);   // GAMMA power control parameter
+				bitvec_write_field(dest, &wp,gamma,5);   // GAMMA power control parameter
 		} else
-			bitvec_write_field(dest, wp,0x0,1); // USF_TN(i): off
+			bitvec_write_field(dest, &wp,0x0,1); // USF_TN(i): off
 	}
-	//	bitvec_write_field(dest, wp,0x0,1); // Measurement Mapping struct not present
+	//	bitvec_write_field(dest, &wp,0x0,1); // Measurement Mapping struct not present
 }
 
 
@@ -603,20 +603,20 @@
 	unsigned wp = 0;
 	int plen;
 
-	bitvec_write_field(dest, wp,0x0,4);  // Skip Indicator
-	bitvec_write_field(dest, wp,0x6,4);  // Protocol Discriminator
-	bitvec_write_field(dest, wp,0x21,8); // Paging Request Message Type
+	bitvec_write_field(dest, &wp,0x0,4);  // Skip Indicator
+	bitvec_write_field(dest, &wp,0x6,4);  // Protocol Discriminator
+	bitvec_write_field(dest, &wp,0x21,8); // Paging Request Message Type
 
-	bitvec_write_field(dest, wp,0x0,4);  // Page Mode
-	bitvec_write_field(dest, wp,0x0,4);  // Channel Needed
+	bitvec_write_field(dest, &wp,0x0,4);  // Page Mode
+	bitvec_write_field(dest, &wp,0x0,4);  // Channel Needed
 
 	// Mobile Identity
-	bitvec_write_field(dest, wp,ptmsi_len+1,8);  // Mobile Identity length
-	bitvec_write_field(dest, wp,0xf,4);          // unused
-	bitvec_write_field(dest, wp,0x4,4);          // PTMSI type
+	bitvec_write_field(dest, &wp,ptmsi_len+1,8);  // Mobile Identity length
+	bitvec_write_field(dest, &wp,0xf,4);          // unused
+	bitvec_write_field(dest, &wp,0x4,4);          // PTMSI type
 	for (int i = 0; i < ptmsi_len; i++)
 	{
-		bitvec_write_field(dest, wp,ptmsi[i],8); // PTMSI
+		bitvec_write_field(dest, &wp,ptmsi[i],8); // PTMSI
 	}
 	if ((wp % 8)) {
 		LOGP(DRLCMACUL, LOGL_ERROR, "Length of PAG.REQ without rest "
@@ -624,12 +624,12 @@
 		exit (0);
 	}
 	plen = wp / 8;
-	bitvec_write_field(dest, wp,0x0,1); // "L" NLN(PCH) = off
-	bitvec_write_field(dest, wp,0x0,1); // "L" Priority1 = off
-	bitvec_write_field(dest, wp,0x1,1); // "L" Priority2 = off
-	bitvec_write_field(dest, wp,0x0,1); // "L" Group Call information = off
-	bitvec_write_field(dest, wp,0x0,1); // "H" Packet Page Indication 1 = packet paging procedure
-	bitvec_write_field(dest, wp,0x1,1); // "H" Packet Page Indication 2 = packet paging procedure
+	bitvec_write_field(dest, &wp,0x0,1); // "L" NLN(PCH) = off
+	bitvec_write_field(dest, &wp,0x0,1); // "L" Priority1 = off
+	bitvec_write_field(dest, &wp,0x1,1); // "L" Priority2 = off
+	bitvec_write_field(dest, &wp,0x0,1); // "L" Group Call information = off
+	bitvec_write_field(dest, &wp,0x0,1); // "H" Packet Page Indication 1 = packet paging procedure
+	bitvec_write_field(dest, &wp,0x1,1); // "H" Packet Page Indication 2 = packet paging procedure
 
 	return plen;
 }
@@ -667,13 +667,13 @@
 	LOGP(DRLCMACUL, LOGL_DEBUG, "- V(N): \"%s\" R=Received "
 		"I=Invalid\n", rbb);
 
-	bitvec_write_field(dest, wp, is_final, 1); // FINAL_ACK_INDICATION
-	bitvec_write_field(dest, wp, window->ssn(), 7); // STARTING_SEQUENCE_NUMBER
+	bitvec_write_field(dest, &wp, is_final, 1); // FINAL_ACK_INDICATION
+	bitvec_write_field(dest, &wp, window->ssn(), 7); // STARTING_SEQUENCE_NUMBER
 
 	for (int i = 0; i < 64; i++) {
 		/* Set bit at the appropriate position (see 3GPP TS 04.60 9.1.8.1) */
 		bool is_ack = (rbb[i] == 'R');
-		bitvec_write_field(dest, wp, is_ack, 1);
+		bitvec_write_field(dest, &wp, is_ack, 1);
 	}
 }
 
@@ -682,20 +682,20 @@
 	struct gprs_rlcmac_ul_tbf *tbf, bool is_final)
 {
 
-	bitvec_write_field(dest, wp, tbf->current_cs().to_num() - 1, 2); // CHANNEL_CODING_COMMAND
+	bitvec_write_field(dest, &wp, tbf->current_cs().to_num() - 1, 2); // CHANNEL_CODING_COMMAND
 	write_packet_ack_nack_desc_gprs(bts, dest, wp, &tbf->m_window, is_final);
 
-	bitvec_write_field(dest, wp, 1, 1); // 1: have CONTENTION_RESOLUTION_TLLI
-	bitvec_write_field(dest, wp, tbf->tlli(), 32); // CONTENTION_RESOLUTION_TLLI
+	bitvec_write_field(dest, &wp, 1, 1); // 1: have CONTENTION_RESOLUTION_TLLI
+	bitvec_write_field(dest, &wp, tbf->tlli(), 32); // CONTENTION_RESOLUTION_TLLI
 
-	bitvec_write_field(dest, wp, 0, 1); // 0: don't have Packet Timing Advance
-	bitvec_write_field(dest, wp, 0, 1); // 0: don't have Power Control Parameters
-	bitvec_write_field(dest, wp, 0, 1); // 0: don't have Extension Bits
-	bitvec_write_field(dest, wp, 0, 1); // fixed 0
-	bitvec_write_field(dest, wp, 1, 1); // 1: have Additions R99
-	bitvec_write_field(dest, wp, 0, 1); // 0: don't have Packet Extended Timing Advance
-	bitvec_write_field(dest, wp, 1, 1); // TBF_EST (enabled)
-	bitvec_write_field(dest, wp, 0, 1); // 0: don't have REL 5
+	bitvec_write_field(dest, &wp, 0, 1); // 0: don't have Packet Timing Advance
+	bitvec_write_field(dest, &wp, 0, 1); // 0: don't have Power Control Parameters
+	bitvec_write_field(dest, &wp, 0, 1); // 0: don't have Extension Bits
+	bitvec_write_field(dest, &wp, 0, 1); // fixed 0
+	bitvec_write_field(dest, &wp, 1, 1); // 1: have Additions R99
+	bitvec_write_field(dest, &wp, 0, 1); // 0: don't have Packet Extended Timing Advance
+	bitvec_write_field(dest, &wp, 1, 1); // TBF_EST (enabled)
+	bitvec_write_field(dest, &wp, 0, 1); // 0: don't have REL 5
 };
 
 static void write_packet_ack_nack_desc_egprs(
@@ -810,37 +810,37 @@
 
 	/* EGPRS Ack/Nack Description IE */
 	if (len_coded == false) {
-		bitvec_write_field(dest, wp, 0, 1); // 0: don't have length
+		bitvec_write_field(dest, &wp, 0, 1); // 0: don't have length
 	} else {
-		bitvec_write_field(dest, wp, 1, 1); // 1: have length
-		bitvec_write_field(dest, wp, len, 8); // length
+		bitvec_write_field(dest, &wp, 1, 1); // 1: have length
+		bitvec_write_field(dest, &wp, len, 8); // length
 	}
 
-	bitvec_write_field(dest, wp, is_final, 1); // FINAL_ACK_INDICATION
-	bitvec_write_field(dest, wp, bow, 1); // BEGINNING_OF_WINDOW
-	bitvec_write_field(dest, wp, eow, 1); // END_OF_WINDOW
-	bitvec_write_field(dest, wp, ssn, 11); // STARTING_SEQUENCE_NUMBER
+	bitvec_write_field(dest, &wp, is_final, 1); // FINAL_ACK_INDICATION
+	bitvec_write_field(dest, &wp, bow, 1); // BEGINNING_OF_WINDOW
+	bitvec_write_field(dest, &wp, eow, 1); // END_OF_WINDOW
+	bitvec_write_field(dest, &wp, ssn, 11); // STARTING_SEQUENCE_NUMBER
 	if (is_compressed) {
-		bitvec_write_field(dest, wp, 1, 1); // CRBB_Exist
-		bitvec_write_field(dest, wp, crbb_len, 7); // CRBB_LENGTH
+		bitvec_write_field(dest, &wp, 1, 1); // CRBB_Exist
+		bitvec_write_field(dest, &wp, crbb_len, 7); // CRBB_LENGTH
 		crbb_start_clr_code = (0x80 & ucmp_vec.data[0])>>7;
-		bitvec_write_field(dest, wp, crbb_start_clr_code, 1); // CRBB_clr_code
+		bitvec_write_field(dest, &wp, crbb_start_clr_code, 1); // CRBB_clr_code
 		LOGP(DRLCMACUL, LOGL_DEBUG,
 			"EGPRS CRBB, crbb_len = %d, crbb_start_clr_code = %d\n",
 			crbb_len, crbb_start_clr_code);
 		while (crbb_len != 0) {
 			if (crbb_len > 8) {
-				bitvec_write_field(dest, wp, crbb_bitmap[iter], 8);
+				bitvec_write_field(dest, &wp, crbb_bitmap[iter], 8);
 				crbb_len = crbb_len - 8;
 				iter++;
 			} else {
-				bitvec_write_field(dest, wp, crbb_bitmap[iter], crbb_len);
+				bitvec_write_field(dest, &wp, crbb_bitmap[iter], crbb_len);
 				crbb_len = 0;
 			}
 		}
 		esn_crbb = window->mod_sns(esn_crbb + uclen_crbb);
 	} else {
-		bitvec_write_field(dest, wp, 0, 1); // CRBB_Exist
+		bitvec_write_field(dest, &wp, 0, 1); // CRBB_Exist
 	}
 	LOGP(DRLCMACUL, LOGL_DEBUG,
 		"EGPRS URBB, urbb len = %d, SSN = %d, ESN_CRBB = %d, "
@@ -853,7 +853,7 @@
 	for (i = urbb_len; i > 0; i--) {
 		/* Set bit at the appropriate position (see 3GPP TS 04.60 12.3.1) */
 		bool is_ack = window->m_v_n.is_received(esn_crbb + i);
-		bitvec_write_field(dest, wp, is_ack, 1);
+		bitvec_write_field(dest, &wp, is_ack, 1);
 	}
 }
 
@@ -861,29 +861,29 @@
 	struct gprs_rlcmac_bts *bts, bitvec * dest, unsigned& wp,
 	struct gprs_rlcmac_ul_tbf *tbf, bool is_final)
 {
-	bitvec_write_field(dest, wp, 0, 2); // fixed 00
+	bitvec_write_field(dest, &wp, 0, 2); // fixed 00
 	/* CHANNEL_CODING_COMMAND */
-	bitvec_write_field(dest, wp,
+	bitvec_write_field(dest, &wp,
 		tbf->current_cs().to_num() - 1, 4);
 	/* 0: no RESEGMENT, 1: Segmentation*/
-	bitvec_write_field(dest, wp, 1, 1);
-	bitvec_write_field(dest, wp, 1, 1); // PRE_EMPTIVE_TRANSMISSION, TODO: This resembles GPRS, change it?
-	bitvec_write_field(dest, wp, 0, 1); // 0: no PRR_RETRANSMISSION_REQUEST, TODO: clarify
-	bitvec_write_field(dest, wp, 0, 1); // 0: no ARAC_RETRANSMISSION_REQUEST, TODO: clarify
-	bitvec_write_field(dest, wp, 1, 1); // 1: have CONTENTION_RESOLUTION_TLLI
-	bitvec_write_field(dest, wp, tbf->tlli(), 32); // CONTENTION_RESOLUTION_TLLI
-	bitvec_write_field(dest, wp, 1, 1); // TBF_EST (enabled)
-	bitvec_write_field(dest, wp, 0, 1); // 0: don't have Packet Timing Advance
-	bitvec_write_field(dest, wp, 0, 1); // 0: don't have Packet Extended Timing Advance
-	bitvec_write_field(dest, wp, 0, 1); // 0: don't have Power Control Parameters
-	bitvec_write_field(dest, wp, 0, 1); // 0: don't have Extension Bits
+	bitvec_write_field(dest, &wp, 1, 1);
+	bitvec_write_field(dest, &wp, 1, 1); // PRE_EMPTIVE_TRANSMISSION, TODO: This resembles GPRS, change it?
+	bitvec_write_field(dest, &wp, 0, 1); // 0: no PRR_RETRANSMISSION_REQUEST, TODO: clarify
+	bitvec_write_field(dest, &wp, 0, 1); // 0: no ARAC_RETRANSMISSION_REQUEST, TODO: clarify
+	bitvec_write_field(dest, &wp, 1, 1); // 1: have CONTENTION_RESOLUTION_TLLI
+	bitvec_write_field(dest, &wp, tbf->tlli(), 32); // CONTENTION_RESOLUTION_TLLI
+	bitvec_write_field(dest, &wp, 1, 1); // TBF_EST (enabled)
+	bitvec_write_field(dest, &wp, 0, 1); // 0: don't have Packet Timing Advance
+	bitvec_write_field(dest, &wp, 0, 1); // 0: don't have Packet Extended Timing Advance
+	bitvec_write_field(dest, &wp, 0, 1); // 0: don't have Power Control Parameters
+	bitvec_write_field(dest, &wp, 0, 1); // 0: don't have Extension Bits
 
 	/* -2 for last bit 0 mandatory and REL5 not supported */
 	unsigned bits_ack_nack = dest->data_len * 8 - wp - 2;
 	write_packet_ack_nack_desc_egprs(bts, dest, wp, &tbf->m_window, is_final, bits_ack_nack);
 
-	bitvec_write_field(dest, wp, 0, 1); // fixed 0
-	bitvec_write_field(dest, wp, 0, 1); // 0: don't have REL 5
+	bitvec_write_field(dest, &wp, 0, 1); // fixed 0
+	bitvec_write_field(dest, &wp, 0, 1); // 0: don't have REL 5
 };
 
 void Encoding::write_packet_uplink_ack(
@@ -896,23 +896,23 @@
 	LOGP(DRLCMACUL, LOGL_DEBUG, "Encoding Ack/Nack for %s "
 		"(final=%d)\n", tbf_name(tbf), is_final);
 
-	bitvec_write_field(dest, wp, 0x1, 2);  // Payload Type
-	bitvec_write_field(dest, wp, rrbp, 2);  // Uplink block with TDMA framenumber
-	bitvec_write_field(dest, wp, is_final, 1);  // Suppl/Polling Bit
-	bitvec_write_field(dest, wp, 0x0, 3);  // Uplink state flag
-	bitvec_write_field(dest, wp, 0x9, 6);  // MESSAGE TYPE Uplink Ack/Nack
-	bitvec_write_field(dest, wp, 0x0, 2);  // Page Mode
+	bitvec_write_field(dest, &wp, 0x1, 2);  // Payload Type
+	bitvec_write_field(dest, &wp, rrbp, 2);  // Uplink block with TDMA framenumber
+	bitvec_write_field(dest, &wp, is_final, 1);  // Suppl/Polling Bit
+	bitvec_write_field(dest, &wp, 0x0, 3);  // Uplink state flag
+	bitvec_write_field(dest, &wp, 0x9, 6);  // MESSAGE TYPE Uplink Ack/Nack
+	bitvec_write_field(dest, &wp, 0x0, 2);  // Page Mode
 
-	bitvec_write_field(dest, wp, 0x0, 2);  // fixed 00
-	bitvec_write_field(dest, wp, tbf->tfi(), 5);  // Uplink TFI
+	bitvec_write_field(dest, &wp, 0x0, 2);  // fixed 00
+	bitvec_write_field(dest, &wp, tbf->tfi(), 5);  // Uplink TFI
 
 	if (tbf->is_egprs_enabled()) {
 		/* PU_AckNack_EGPRS = on */
-		bitvec_write_field(dest, wp, 1, 1);  // 1: EGPRS
+		bitvec_write_field(dest, &wp, 1, 1);  // 1: EGPRS
 		write_packet_uplink_ack_egprs(bts, dest, wp, tbf, is_final);
 	} else {
 		/* PU_AckNack_GPRS = on */
-		bitvec_write_field(dest, wp, 0, 1);  // 0: GPRS
+		bitvec_write_field(dest, &wp, 0, 1);  // 0: GPRS
 		write_packet_uplink_ack_gprs(bts, dest, wp, tbf, is_final);
 	}
 
@@ -926,15 +926,15 @@
 {
 	unsigned wp = 0;
 
-	bitvec_write_field(dest, wp,0x1,2);  // Payload Type
-	bitvec_write_field(dest, wp,0x0,3);  // No polling
-	bitvec_write_field(dest, wp,0x0,3);  // Uplink state flag
-	bitvec_write_field(dest, wp,0x22,6);  // MESSAGE TYPE
+	bitvec_write_field(dest, &wp,0x1,2);  // Payload Type
+	bitvec_write_field(dest, &wp,0x0,3);  // No polling
+	bitvec_write_field(dest, &wp,0x0,3);  // Uplink state flag
+	bitvec_write_field(dest, &wp,0x22,6);  // MESSAGE TYPE
 
-	bitvec_write_field(dest, wp,0x0,2);  // Page Mode
+	bitvec_write_field(dest, &wp,0x0,2);  // Page Mode
 
-	bitvec_write_field(dest, wp,0x0,1);  // No PERSISTENCE_LEVEL
-	bitvec_write_field(dest, wp,0x0,1);  // No NLN
+	bitvec_write_field(dest, &wp,0x0,1);  // No PERSISTENCE_LEVEL
+	bitvec_write_field(dest, &wp,0x0,1);  // No NLN
 
 	return wp;
 }
@@ -942,24 +942,24 @@
 unsigned Encoding::write_repeated_page_info(bitvec * dest, unsigned& wp, uint8_t len,
 	uint8_t *identity, uint8_t chan_needed)
 {
-	bitvec_write_field(dest, wp,0x1,1);  // Repeated Page info exists
+	bitvec_write_field(dest, &wp,0x1,1);  // Repeated Page info exists
 
-	bitvec_write_field(dest, wp,0x1,1);  // RR connection paging
+	bitvec_write_field(dest, &wp,0x1,1);  // RR connection paging
 
 	if ((identity[0] & 0x07) == 4) {
-		bitvec_write_field(dest, wp,0x0,1);  // TMSI
+		bitvec_write_field(dest, &wp,0x0,1);  // TMSI
 		identity++;
 		len--;
 	} else {
-		bitvec_write_field(dest, wp,0x0,1);  // MI
-		bitvec_write_field(dest, wp,len,4);  // MI len
+		bitvec_write_field(dest, &wp,0x0,1);  // MI
+		bitvec_write_field(dest, &wp,len,4);  // MI len
 	}
 	while (len) {
-		bitvec_write_field(dest, wp,*identity++,8);  // MI data
+		bitvec_write_field(dest, &wp,*identity++,8);  // MI data
 		len--;
 	}
-	bitvec_write_field(dest, wp,chan_needed,2);  // CHANNEL_NEEDED
-	bitvec_write_field(dest, wp,0x0,1);  // No eMLPP_PRIORITY
+	bitvec_write_field(dest, &wp,chan_needed,2);  // CHANNEL_NEEDED
+	bitvec_write_field(dest, &wp,0x0,1);  // No eMLPP_PRIORITY
 
 	return wp;
 }
@@ -1490,17 +1490,17 @@
 {
 	unsigned wp = 0;
 
-	bitvec_write_field(dest, wp, 0x1, 2);  // Payload Type
-	bitvec_write_field(dest, wp, 0x0, 2);  // Uplink block with TDMA FN
-	bitvec_write_field(dest, wp, 0, 1);  // No Polling Bit
-	bitvec_write_field(dest, wp, 0x0, 3);  // Uplink state flag
-	bitvec_write_field(dest, wp,
+	bitvec_write_field(dest, &wp, 0x1, 2);  // Payload Type
+	bitvec_write_field(dest, &wp, 0x0, 2);  // Uplink block with TDMA FN
+	bitvec_write_field(dest, &wp, 0, 1);  // No Polling Bit
+	bitvec_write_field(dest, &wp, 0x0, 3);  // Uplink state flag
+	bitvec_write_field(dest, &wp,
 				MT_PACKET_ACCESS_REJECT, 6);  // MESSAGE TYPE
-	bitvec_write_field(dest, wp, 0, 2); // fixed 00
-	bitvec_write_field(dest, wp, 0x0, 1);  //  TLLI / G-RNTI : bit (32)
-	bitvec_write_field(dest, wp, tlli, 32); // CONTENTION_RESOLUTION_TLLI
-	bitvec_write_field(dest, wp, 1, 1);  //  WAIT_INDICATION size in seconds
+	bitvec_write_field(dest, &wp, 0, 2); // fixed 00
+	bitvec_write_field(dest, &wp, 0x0, 1);  //  TLLI / G-RNTI : bit (32)
+	bitvec_write_field(dest, &wp, tlli, 32); // CONTENTION_RESOLUTION_TLLI
+	bitvec_write_field(dest, &wp, 1, 1);  //  WAIT_INDICATION size in seconds
 	/* TODO: make it configurable */
-	bitvec_write_field(dest, wp, 5, 8);  //  WAIT_INDICATION value
-	bitvec_write_field(dest, wp, 0, 1);  //  WAIT_INDICATION size in seconds
+	bitvec_write_field(dest, &wp, 5, 8);  //  WAIT_INDICATION value
+	bitvec_write_field(dest, &wp, 0, 1);  //  WAIT_INDICATION size in seconds
 }
diff --git a/src/gprs_bssgp_pcu.cpp b/src/gprs_bssgp_pcu.cpp
index da1d26c..71bd139 100644
--- a/src/gprs_bssgp_pcu.cpp
+++ b/src/gprs_bssgp_pcu.cpp
@@ -90,7 +90,7 @@
 
 	LOGP(DBSSGP, LOGL_DEBUG, "Got BSSGP RA Capability of size %d\n", cap_len);
 
-	block = bitvec_alloc(cap_len);
+	block = bitvec_alloc(cap_len, tall_pcu_ctx);
 	bitvec_unpack(block, cap);
 
 	/* TS 24.008, 10.5.5.12a */
diff --git a/src/gprs_rlcmac.cpp b/src/gprs_rlcmac.cpp
index ac8f2d1..16870c3 100644
--- a/src/gprs_rlcmac.cpp
+++ b/src/gprs_rlcmac.cpp
@@ -33,7 +33,7 @@
 	const char *imsi)
 {
 	LOGP(DRLCMAC, LOGL_NOTICE, "TX: [PCU -> BTS] Paging Request (CCCH)\n");
-	bitvec *paging_request = bitvec_alloc(23);
+	bitvec *paging_request = bitvec_alloc(23, tall_pcu_ctx);
 	bitvec_unhex(paging_request, "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
 	int plen = Encoding::write_paging_request(paging_request, ptmsi, ptmsi_len);
 	pcu_l1if_tx_pch(paging_request, plen, (char *)imsi);
diff --git a/src/gprs_rlcmac.h b/src/gprs_rlcmac.h
index 589bd8f..be1e686 100644
--- a/src/gprs_rlcmac.h
+++ b/src/gprs_rlcmac.h
@@ -22,13 +22,13 @@
 #define GPRS_RLCMAC_H
 
 #ifdef __cplusplus
-#include <bitvector.h>
 #include <gsm_rlcmac.h>
 #include <gsm_timer.h>
 
 extern "C" {
 #include <osmocom/core/linuxlist.h>
 #include <osmocom/core/timer.h>
+#include <osmocom/core/bitvec.h>
 }
 #endif
 
diff --git a/src/gsm_rlcmac.cpp b/src/gsm_rlcmac.cpp
index 6b43aa6..6323b09 100644
--- a/src/gsm_rlcmac.cpp
+++ b/src/gsm_rlcmac.cpp
@@ -4799,7 +4799,7 @@
 {
   csnStream_t      ar;
   unsigned readIndex = 0;
-  guint8 payload_type = bitvec_read_field(vector, readIndex, 2);
+  guint8 payload_type = bitvec_read_field(vector, &readIndex, 2);
 
   if (payload_type == PAYLOAD_TYPE_DATA)
   {
@@ -4814,7 +4814,7 @@
   data->NrOfBits = 23 * 8;
   csnStreamInit(&ar, 0, data->NrOfBits);
   readIndex += 6;
-  data->u.MESSAGE_TYPE = bitvec_read_field(vector, readIndex, 6);
+  data->u.MESSAGE_TYPE = bitvec_read_field(vector, &readIndex, 6);
   readIndex = 0;
   switch (data->u.MESSAGE_TYPE)
   {
@@ -4907,10 +4907,10 @@
   gint bit_offset = 0;
   gint bit_length;
   unsigned readIndex = 0;
-  data->PAYLOAD_TYPE = bitvec_read_field(vector, readIndex, 2);
-  data->RRBP = bitvec_read_field(vector, readIndex, 2);
-  data->SP = bitvec_read_field(vector, readIndex, 1);
-  data->USF = bitvec_read_field(vector, readIndex, 3);
+  data->PAYLOAD_TYPE = bitvec_read_field(vector, &readIndex, 2);
+  data->RRBP = bitvec_read_field(vector, &readIndex, 2);
+  data->SP = bitvec_read_field(vector, &readIndex, 1);
+  data->USF = bitvec_read_field(vector, &readIndex, 3);
 
   if (data->PAYLOAD_TYPE == PAYLOAD_TYPE_DATA)
   {
@@ -4929,27 +4929,27 @@
     bit_offset = 8;
     if (data->PAYLOAD_TYPE == PAYLOAD_TYPE_CTRL_OPT_OCTET)
     {
-      data->RBSN = bitvec_read_field(vector, readIndex, 1);
-      data->RTI = bitvec_read_field(vector, readIndex, 5);
-      data->FS = bitvec_read_field(vector, readIndex, 1);
-      data->AC = bitvec_read_field(vector, readIndex, 1);
+      data->RBSN = bitvec_read_field(vector, &readIndex, 1);
+      data->RTI = bitvec_read_field(vector, &readIndex, 5);
+      data->FS = bitvec_read_field(vector, &readIndex, 1);
+      data->AC = bitvec_read_field(vector, &readIndex, 1);
       bit_offset += 8;
       if (data->AC == 1)
       {
-        data->PR = bitvec_read_field(vector, readIndex, 2);
-        data->TFI = bitvec_read_field(vector, readIndex, 5);
-        data->D = bitvec_read_field(vector, readIndex, 1);
+	data->PR = bitvec_read_field(vector, &readIndex, 2);
+	data->TFI = bitvec_read_field(vector, &readIndex, 5);
+	data->D = bitvec_read_field(vector, &readIndex, 1);
         bit_offset += 8;
       }
       if ((data->RBSN == 1) && (data->FS == 0))
       {
-        data->RBSNe = bitvec_read_field(vector, readIndex, 3);
-        data->FSe = bitvec_read_field(vector, readIndex, 1);
-        data->spare = bitvec_read_field(vector, readIndex, 4);
+	data->RBSNe = bitvec_read_field(vector, &readIndex, 3);
+	data->FSe = bitvec_read_field(vector, &readIndex, 1);
+	data->spare = bitvec_read_field(vector, &readIndex, 4);
         bit_offset += 8;
       }
     }
-    data->u.MESSAGE_TYPE = bitvec_read_field(vector, readIndex, 6);
+    data->u.MESSAGE_TYPE = bitvec_read_field(vector, &readIndex, 6);
   }
 
   /* Initialize the contexts */
@@ -5206,30 +5206,30 @@
   else
   {
     /* First print the message type and create a tree item */
-    bitvec_write_field(vector, writeIndex, data->PAYLOAD_TYPE, 2);
-    bitvec_write_field(vector, writeIndex, data->RRBP, 2);
-    bitvec_write_field(vector, writeIndex, data->SP, 1);
-    bitvec_write_field(vector, writeIndex, data->USF, 3);
+    bitvec_write_field(vector, &writeIndex, data->PAYLOAD_TYPE, 2);
+    bitvec_write_field(vector, &writeIndex, data->RRBP, 2);
+    bitvec_write_field(vector, &writeIndex, data->SP, 1);
+    bitvec_write_field(vector, &writeIndex, data->USF, 3);
     bit_offset = 8;
     if (data->PAYLOAD_TYPE == PAYLOAD_TYPE_CTRL_OPT_OCTET)
     {
-      bitvec_write_field(vector, writeIndex, data->RBSN, 1);
-      bitvec_write_field(vector, writeIndex, data->RTI, 5);
-      bitvec_write_field(vector, writeIndex, data->FS, 1);
-      bitvec_write_field(vector, writeIndex, data->AC, 1);
+      bitvec_write_field(vector, &writeIndex, data->RBSN, 1);
+      bitvec_write_field(vector, &writeIndex, data->RTI, 5);
+      bitvec_write_field(vector, &writeIndex, data->FS, 1);
+      bitvec_write_field(vector, &writeIndex, data->AC, 1);
       bit_offset += 8;
       if (data->AC == 1)
       {
-        bitvec_write_field(vector, writeIndex, data->PR, 2);
-        bitvec_write_field(vector, writeIndex, data->TFI, 5);
-        bitvec_write_field(vector, writeIndex, data->D, 1);
+	bitvec_write_field(vector, &writeIndex, data->PR, 2);
+	bitvec_write_field(vector, &writeIndex, data->TFI, 5);
+	bitvec_write_field(vector, &writeIndex, data->D, 1);
         bit_offset += 8;
       }
       if ((data->RBSN == 1) && (data->FS == 0))
       {
-        bitvec_write_field(vector, writeIndex, data->RBSNe, 3);
-        bitvec_write_field(vector, writeIndex, data->FSe, 1);
-        bitvec_write_field(vector, writeIndex, data->spare, 4);
+	bitvec_write_field(vector, &writeIndex, data->RBSNe, 3);
+	bitvec_write_field(vector, &writeIndex, data->FSe, 1);
+	bitvec_write_field(vector, &writeIndex, data->spare, 4);
         bit_offset += 8;
       }
     }
@@ -5378,32 +5378,32 @@
 {
   unsigned readIndex = 0;
   //unsigned dataLen = 0;
-  guint8 payload_type = bitvec_read_field(vector, readIndex, 2);
+  guint8 payload_type = bitvec_read_field(vector, &readIndex, 2);
   if (payload_type == PAYLOAD_TYPE_DATA)
   {
     readIndex = 0;
     // MAC header
-    data->PAYLOAD_TYPE = bitvec_read_field(vector, readIndex, 2);
-    data->CV = bitvec_read_field(vector, readIndex, 4);
-    data->SI = bitvec_read_field(vector, readIndex, 1);
-    data->R = bitvec_read_field(vector, readIndex, 1);
+    data->PAYLOAD_TYPE = bitvec_read_field(vector, &readIndex, 2);
+    data->CV = bitvec_read_field(vector, &readIndex, 4);
+    data->SI = bitvec_read_field(vector, &readIndex, 1);
+    data->R = bitvec_read_field(vector, &readIndex, 1);
     LOGPC(DRLCMACDATA, LOGL_NOTICE, "PAYLOAD_TYPE = %u ", (unsigned)(data->PAYLOAD_TYPE));
     LOGPC(DRLCMACDATA, LOGL_NOTICE, "CV = %u ", (unsigned)(data->CV));
     LOGPC(DRLCMACDATA, LOGL_NOTICE, "SI = %u ", (unsigned)(data->SI));
     LOGPC(DRLCMACDATA, LOGL_NOTICE, "R = %u ", (unsigned)(data->R));
     // Octet 1
-    data->spare = bitvec_read_field(vector, readIndex, 1);
-    data->PI = bitvec_read_field(vector, readIndex, 1);
-    data->TFI = bitvec_read_field(vector, readIndex, 5);
-    data->TI = bitvec_read_field(vector, readIndex, 1);
+    data->spare = bitvec_read_field(vector, &readIndex, 1);
+    data->PI = bitvec_read_field(vector, &readIndex, 1);
+    data->TFI = bitvec_read_field(vector, &readIndex, 5);
+    data->TI = bitvec_read_field(vector, &readIndex, 1);
     LOGPC(DRLCMACDATA, LOGL_NOTICE, "spare = %u ", (unsigned)(data->spare));
     LOGPC(DRLCMACDATA, LOGL_NOTICE, "PI = %u ", (unsigned)(data->PI));
     LOGPC(DRLCMACDATA, LOGL_NOTICE, "TFI = %u ", (unsigned)(data->TFI));
     LOGPC(DRLCMACDATA, LOGL_NOTICE, "TI = %u ", (unsigned)(data->TI));
 
     // Octet 2
-    data->BSN = bitvec_read_field(vector, readIndex, 7);
-    data->E_1 = bitvec_read_field(vector, readIndex, 1);
+    data->BSN = bitvec_read_field(vector, &readIndex, 7);
+    data->E_1 = bitvec_read_field(vector, &readIndex, 1);
     LOGPC(DRLCMACDATA, LOGL_NOTICE, "BSN = %u ", (unsigned)(data->BSN));
     LOGPC(DRLCMACDATA, LOGL_NOTICE, "E_1 = %u ", (unsigned)(data->E_1));
 
@@ -5414,9 +5414,9 @@
       unsigned i = 0;
       do
       {
-        data->LENGTH_INDICATOR[i] = bitvec_read_field(vector, readIndex, 6);
-        data->M[i] = bitvec_read_field(vector, readIndex, 1);
-        data->E[i] = bitvec_read_field(vector, readIndex, 1);
+	data->LENGTH_INDICATOR[i] = bitvec_read_field(vector, &readIndex, 6);
+	data->M[i] = bitvec_read_field(vector, &readIndex, 1);
+	data->E[i] = bitvec_read_field(vector, &readIndex, 1);
         LOGPC(DRLCMACDATA, LOGL_NOTICE, "LENGTH_INDICATOR[%u] = %u ", i, (unsigned)(data->LENGTH_INDICATOR[i]));
         LOGPC(DRLCMACDATA, LOGL_NOTICE, "M[%u] = %u ", i, (unsigned)(data->M[i]));
         LOGPC(DRLCMACDATA, LOGL_NOTICE, "E[%u] = %u ", i, (unsigned)(data->E[i]));
@@ -5425,12 +5425,12 @@
     }
     if(data->TI == 1) // TLLI field is present
     {
-      data->TLLI = bitvec_read_field(vector, readIndex, 32);
+      data->TLLI = bitvec_read_field(vector, &readIndex, 32);
       LOGPC(DRLCMACDATA, LOGL_NOTICE, "TLLI = %08x ", data->TLLI);
       if (data->PI == 1) // PFI is present if TI field indicates presence of TLLI
       {
-        data->PFI = bitvec_read_field(vector, readIndex, 7);
-        data->E_2 = bitvec_read_field(vector, readIndex, 1);
+	data->PFI = bitvec_read_field(vector, &readIndex, 7);
+	data->E_2 = bitvec_read_field(vector, &readIndex, 1);
         LOGPC(DRLCMACDATA, LOGL_NOTICE, "PFI = %u ", (unsigned)(data->PFI));
         LOGPC(DRLCMACDATA, LOGL_NOTICE, "E_2 = %u ", (unsigned)(data->E_2));
       }
@@ -5440,7 +5440,7 @@
     assert(dataLen <= 20);
     for (unsigned i = 0; i < dataLen; i++)
     {
-      data->RLC_DATA[i] = bitvec_read_field(vector, readIndex, 8);
+      data->RLC_DATA[i] = bitvec_read_field(vector, &readIndex, 8);
       LOGPC(DRLCMACDATA, LOGL_NOTICE, "%02x", (unsigned)(data->RLC_DATA[i]));
     }
     LOGPC(DRLCMACDATA, LOGL_NOTICE, "\n");
@@ -5459,26 +5459,26 @@
   if (data->PAYLOAD_TYPE == PAYLOAD_TYPE_DATA)
   {
     // MAC header
-    bitvec_write_field(vector, writeIndex, data->PAYLOAD_TYPE, 2);
-    bitvec_write_field(vector, writeIndex, data->RRBP, 2);
-    bitvec_write_field(vector, writeIndex, data->SP, 1);
-    bitvec_write_field(vector, writeIndex, data->USF, 3);
+    bitvec_write_field(vector, &writeIndex, data->PAYLOAD_TYPE, 2);
+    bitvec_write_field(vector, &writeIndex, data->RRBP, 2);
+    bitvec_write_field(vector, &writeIndex, data->SP, 1);
+    bitvec_write_field(vector, &writeIndex, data->USF, 3);
     LOGPC(DRLCMACDATA, LOGL_NOTICE, "PAYLOAD_TYPE = %u ", (unsigned)(data->PAYLOAD_TYPE));
     LOGPC(DRLCMACDATA, LOGL_NOTICE, "RRBP = %u ", (unsigned)(data->RRBP));
     LOGPC(DRLCMACDATA, LOGL_NOTICE, "SP = %u ", (unsigned)(data->SP));
     LOGPC(DRLCMACDATA, LOGL_NOTICE, "USF = %u ", (unsigned)(data->USF));
     
     // Octet 1
-    bitvec_write_field(vector, writeIndex, data->PR, 2);
-    bitvec_write_field(vector, writeIndex, data->TFI, 5);
-    bitvec_write_field(vector, writeIndex, data->FBI, 1);
+    bitvec_write_field(vector, &writeIndex, data->PR, 2);
+    bitvec_write_field(vector, &writeIndex, data->TFI, 5);
+    bitvec_write_field(vector, &writeIndex, data->FBI, 1);
     LOGPC(DRLCMACDATA, LOGL_NOTICE, "PR = %u ", (unsigned)(data->PR));
     LOGPC(DRLCMACDATA, LOGL_NOTICE, "TFI = %u ", (unsigned)(data->TFI));
     LOGPC(DRLCMACDATA, LOGL_NOTICE, "FBI = %u ", (unsigned)(data->FBI));
 
     // Octet 2
-    bitvec_write_field(vector, writeIndex, data->BSN, 7);
-    bitvec_write_field(vector, writeIndex, data->E_1, 1);
+    bitvec_write_field(vector, &writeIndex, data->BSN, 7);
+    bitvec_write_field(vector, &writeIndex, data->E_1, 1);
     LOGPC(DRLCMACDATA, LOGL_NOTICE, "BSN = %u ", (unsigned)(data->BSN));
     LOGPC(DRLCMACDATA, LOGL_NOTICE, "E_1 = %u ", (unsigned)(data->E_1));
 
@@ -5488,9 +5488,9 @@
       unsigned i = 0;
       do
       {
-        bitvec_write_field(vector, writeIndex, data->LENGTH_INDICATOR[i], 6);
-        bitvec_write_field(vector, writeIndex, data->M[i], 1);
-        bitvec_write_field(vector, writeIndex, data->E[i], 1);
+	bitvec_write_field(vector, &writeIndex, data->LENGTH_INDICATOR[i], 6);
+	bitvec_write_field(vector, &writeIndex, data->M[i], 1);
+	bitvec_write_field(vector, &writeIndex, data->E[i], 1);
         LOGPC(DRLCMACDATA, LOGL_NOTICE, "LENGTH_INDICATOR[%u] = %u ", i, (unsigned)(data->LENGTH_INDICATOR[i]));
         LOGPC(DRLCMACDATA, LOGL_NOTICE, "M[%u] = %u ", i, (unsigned)(data->M[i]));
         LOGPC(DRLCMACDATA, LOGL_NOTICE, "E[%u] = %u ", i, (unsigned)(data->E[i]));
@@ -5503,7 +5503,7 @@
     assert(dataNumOctets <= 20);
     for (unsigned i = 0; i < dataNumOctets; i++)
     {
-      bitvec_write_field(vector, writeIndex, data->RLC_DATA[i], 8);
+      bitvec_write_field(vector, &writeIndex, data->RLC_DATA[i], 8);
       LOGPC(DRLCMACDATA, LOGL_NOTICE, "%02x", (unsigned)(data->RLC_DATA[i]));
     }
     LOGPC(DRLCMACDATA, LOGL_NOTICE, "\n");
diff --git a/src/pcu_main.cpp b/src/pcu_main.cpp
index 0a0362b..c61eb6d 100644
--- a/src/pcu_main.cpp
+++ b/src/pcu_main.cpp
@@ -168,7 +168,6 @@
 	tall_pcu_ctx = talloc_named_const(NULL, 1, "Osmo-PCU context");
 	if (!tall_pcu_ctx)
 		return -ENOMEM;
-	bv_tall_ctx = tall_pcu_ctx;
 
 	bts = bts_main_data();
 	bts->fc_interval = 1;
diff --git a/src/tbf.cpp b/src/tbf.cpp
index 0d28c5c..2c0c07f 100644
--- a/src/tbf.cpp
+++ b/src/tbf.cpp
@@ -1112,7 +1112,7 @@
 	msg = msgb_alloc(23, "rlcmac_dl_ass");
 	if (!msg)
 		return NULL;
-	bitvec *ass_vec = bitvec_alloc(23);
+	bitvec *ass_vec = bitvec_alloc(23, tall_pcu_ctx);
 	if (!ass_vec) {
 		msgb_free(msg);
 		return NULL;
@@ -1159,7 +1159,7 @@
 
 	msg = msgb_alloc(23, "rlcmac_ul_ass_rej");
 
-	bitvec *packet_access_rej = bitvec_alloc(23);
+	bitvec *packet_access_rej = bitvec_alloc(23, tall_pcu_ctx);
 
 	bitvec_unhex(packet_access_rej,
 		"2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
@@ -1216,7 +1216,7 @@
 	if (!msg)
 		return NULL;
 	LOGP(DRLCMAC, LOGL_INFO, "%ss start Packet Uplink Assignment (PACCH)\n", tbf_name(new_tbf));
-	bitvec *ass_vec = bitvec_alloc(23);
+	bitvec *ass_vec = bitvec_alloc(23, tall_pcu_ctx);
 	if (!ass_vec) {
 		msgb_free(msg);
 		return NULL;
diff --git a/src/tbf_ul.cpp b/src/tbf_ul.cpp
index 2598174..1eee41a 100644
--- a/src/tbf_ul.cpp
+++ b/src/tbf_ul.cpp
@@ -121,7 +121,7 @@
 	msg = msgb_alloc(23, "rlcmac_ul_ack");
 	if (!msg)
 		return NULL;
-	bitvec *ack_vec = bitvec_alloc(23);
+	bitvec *ack_vec = bitvec_alloc(23, tall_pcu_ctx);
 	if (!ack_vec) {
 		msgb_free(msg);
 		return NULL;
diff --git a/tests/rlcmac/RLCMACTest.cpp b/tests/rlcmac/RLCMACTest.cpp
index 97e5e60..9155809 100644
--- a/tests/rlcmac/RLCMACTest.cpp
+++ b/tests/rlcmac/RLCMACTest.cpp
@@ -83,9 +83,9 @@
 	cout << "sizeof PSI5_t                " << sizeof(PSI5_t) << endl;
 }
 
-void testRlcMacDownlink()
+void testRlcMacDownlink(void *test_ctx)
 {
-	struct bitvec *resultVector = bitvec_alloc(23);
+	struct bitvec *resultVector = bitvec_alloc(23, test_ctx);
 	bitvec_unhex(resultVector, "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
 
 	std::string testData[] = {
@@ -106,7 +106,7 @@
 	cout << " DOWNLINK " << endl;
 	for (int i = 0; i < testDataSize; i++)
 	{
-		bitvec *vector = bitvec_alloc(23);
+		bitvec *vector = bitvec_alloc(23, test_ctx);
 		bitvec_unhex(vector, testData[i].c_str());
 		cout << "vector1 = ";
 		for (int i = 0; i < 23; i++)
@@ -150,9 +150,9 @@
 }
 
 
-void testRlcMacUplink()
+void testRlcMacUplink(void *test_ctx)
 {
-	struct bitvec *resultVector = bitvec_alloc(23);
+	struct bitvec *resultVector = bitvec_alloc(23, test_ctx);
 	bitvec_unhex(resultVector, "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
 
 	std::string testData[] = {
@@ -169,7 +169,7 @@
 	cout << " UPLINK " << endl;
 	for (int i = 0; i < testDataSize; i++)
 	{
-		bitvec *vector = bitvec_alloc(23);
+		bitvec *vector = bitvec_alloc(23, test_ctx);
 		bitvec_unhex(vector, testData[i].c_str());
 		cout << "vector1 = ";
 		for (int i = 0; i < 23; i++)
@@ -212,9 +212,9 @@
 	bitvec_free(resultVector);
 }
 
-void testCsnLeftAlignedVarBmpBounds()
+void testCsnLeftAlignedVarBmpBounds(void *test_ctx)
 {
-	bitvec *vector = bitvec_alloc(23);
+	bitvec *vector = bitvec_alloc(23, test_ctx);
 
 	bitvec_unhex(vector, "40200bffd161003e0e519ffffffb800000000000000000");
 	RlcMacUplink_t data;
@@ -229,10 +229,12 @@
 
 int main(int argc, char *argv[])
 {
+	void *ctx = talloc_named_const(NULL, 1, "RLCMACTest");
 	osmo_init_logging(&gprs_log_info);
 
 	//printSizeofRLCMAC();
-	testRlcMacDownlink();
-	testRlcMacUplink();
-	testCsnLeftAlignedVarBmpBounds();
+	testRlcMacDownlink(ctx);
+	testRlcMacUplink(ctx);
+	testCsnLeftAlignedVarBmpBounds(ctx);
+	talloc_free(ctx);
 }
diff --git a/tests/tbf/TbfTest.cpp b/tests/tbf/TbfTest.cpp
index e367ce6..f042262 100644
--- a/tests/tbf/TbfTest.cpp
+++ b/tests/tbf/TbfTest.cpp
@@ -595,7 +595,7 @@
 
 	meas.set_rssi(31);
 
-	rlc_block = bitvec_alloc(23);
+	rlc_block = bitvec_alloc(23, tall_pcu_ctx);
 
 	encode_gsm_rlcmac_uplink(rlc_block, ulreq);
 	num_bytes = bitvec_pack(rlc_block, &buf[0]);
@@ -2573,7 +2573,7 @@
 
 	OSMO_ASSERT(dl_tbf->state_is(GPRS_RLCMAC_FLOW));
 
-	block = bitvec_alloc(23);
+	block = bitvec_alloc(23, tall_pcu_ctx);
 
 	bitvec_unpack(block, data_msg);
 
diff --git a/tests/types/TypesTest.cpp b/tests/types/TypesTest.cpp
index ee1c817..7d09108 100644
--- a/tests/types/TypesTest.cpp
+++ b/tests/types/TypesTest.cpp
@@ -430,7 +430,7 @@
 void test_immediate_assign_rej()
 {
 	uint8_t plen;
-	bitvec *immediate_assignment_rej = bitvec_alloc(22);
+	bitvec *immediate_assignment_rej = bitvec_alloc(22, tall_pcu_ctx);
 
 	bitvec_unhex(immediate_assignment_rej,
 		"2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");

-- 
To view, visit https://gerrit.osmocom.org/1753
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Id8f797631d89aa12b6e48efb2dc153a3e2f059f7
Gerrit-PatchSet: 1
Gerrit-Project: osmo-pcu
Gerrit-Branch: master
Gerrit-Owner: lynxis lazus <lynxis at fe80.eu>


More information about the gerrit-log mailing list