HACK: send Packet Access Reject from rcv_resource_request()

Change-Id: I32959c61687764c858d9f21a828b03500ace8d65
diff --git a/src/encoding.cpp b/src/encoding.cpp
index a4a14dd..f8fd1f8 100644
--- a/src/encoding.cpp
+++ b/src/encoding.cpp
@@ -1639,3 +1639,60 @@
 	bitvec_write_field(dest, &wp, 5, 8);  //  WAIT_INDICATION value
 	bitvec_write_field(dest, &wp, 0, 1);  //  WAIT_INDICATION size in seconds
 }
+
+void Encoding::write_packet_access_reject_tfi(struct bitvec *dest, uint8_t tfi, bool ul)
+{
+	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,
+				MT_PACKET_ACCESS_REJECT, 6);  // MESSAGE TYPE
+	bitvec_write_field(dest, &wp, 0, 2); // fixed 00
+	bitvec_write_field(dest, &wp, 0x03, 2);  //  Global TFI
+	bitvec_write_field(dest, &wp, !ul, 1);  //  Uplink / Downlink
+	bitvec_write_field(dest, &wp, tfi, 5); // TFI
+	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
+}
+
+#if 0
+void Encoding::write_packet_access_reject_tfi(struct bitvec *bv, uint8_t tfi, bool ul)
+{
+	/* The PACKET ACCESS REJECT message (with RLC header) */
+	Packet_Access_Reject_t RejectMsg = {
+		.MESSAGE_TYPE = MT_PACKET_ACCESS_REJECT,
+		.PAGE_MODE = 0x00, /* Normal Paging */
+
+		.Count_Reject = 1,
+	};
+
+	/* Prepare the identity part (Global TFI) */
+	RejectID_t RejectID = { .UnionType = 0x03 };
+	if (ul) {
+		RejectID.u.Global_TFI.UnionType = 0x00;
+		RejectID.u.Global_TFI.u.UPLINK_TFI = tfi;
+	} else {
+		RejectID.u.Global_TFI.UnionType = 0x01;
+		RejectID.u.Global_TFI.u.DOWNLINK_TFI = tfi;
+	}
+
+	RejectMsg.Reject[0] = (Reject_t) {
+		.ID = RejectID,
+		.Exist_Wait = 0,
+	};
+
+	/* Complete block with both MAC and RLC headers */
+	RlcMacDownlink_t dl_block = {
+		.u = { .Packet_Access_Reject = RejectMsg },
+		.PAYLOAD_TYPE = PAYLOAD_TYPE_CTRL_NO_OPT_OCTET,
+		.USF = 7, /* Why should we deal with MAC header here?!? */
+	};
+
+	OSMO_ASSERT(encode_gsm_rlcmac_downlink(bv, &dl_block) == 0);
+}
+#endif
diff --git a/src/encoding.h b/src/encoding.h
index 2365f07..e38febb 100644
--- a/src/encoding.h
+++ b/src/encoding.h
@@ -73,6 +73,8 @@
 	static void write_packet_access_reject(
 		bitvec * dest, uint32_t tlli);
 
+	static void write_packet_access_reject_tfi(struct bitvec *bv, uint8_t tfi, bool ul);
+
 	static void write_packet_uplink_ack(
 			bitvec * dest, struct gprs_rlcmac_ul_tbf *tbf, bool is_final,
 			uint8_t rrbp);
diff --git a/src/gprs_rlcmac_sched.cpp b/src/gprs_rlcmac_sched.cpp
index fe6f159..032e006 100644
--- a/src/gprs_rlcmac_sched.cpp
+++ b/src/gprs_rlcmac_sched.cpp
@@ -172,6 +172,12 @@
 			if (!tbf)
 				continue;
 
+			/* HACK: send PACKET ACCESS REJECT if needed */
+			if ((msg = tbf->sched_pkt_acc_req) != NULL) {
+				tbf->sched_pkt_acc_req = NULL;
+				return msg;
+			}
+
 			/*
 			 * Assignments for the same direction have lower precedence,
 			 * because they may kill the TBF when the CONTROL ACK is
diff --git a/src/pdch.cpp b/src/pdch.cpp
index f46acc8..22e20e3 100644
--- a/src/pdch.cpp
+++ b/src/pdch.cpp
@@ -638,6 +638,12 @@
 		return;
 	}
 
+	struct msgb *msg = msgb_alloc(23, "access_reject");
+	struct bitvec bv = {
+		.data_len = GSM_MACBLOCK_LEN,
+		.data = msgb_put(msg, GSM_MACBLOCK_LEN)
+	};
+
 	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;
@@ -648,6 +654,8 @@
 		}
 		LOGPTBFDL(dl_tbf, LOGL_ERROR,
 			"RX: [PCU <- BTS] FIXME: Packet resource request\n");
+		Encoding::write_packet_access_reject_tfi(&bv, tfi, false);
+		dl_tbf->sched_pkt_acc_req = msg;
 
 		/* Reset N3101 counter: */
 		dl_tbf->n_reset(N3101);
@@ -661,6 +669,8 @@
 		}
 		LOGPTBFUL(ul_tbf, LOGL_ERROR,
 			"RX: [PCU <- BTS] FIXME: Packet resource request\n");
+		Encoding::write_packet_access_reject_tfi(&bv, tfi, true);
+		ul_tbf->sched_pkt_acc_req = msg;
 
 		/* Reset N3101 counter: */
 		ul_tbf->n_reset(N3101);
diff --git a/src/tbf.cpp b/src/tbf.cpp
index 73d7ea9..58139d1 100644
--- a/src/tbf.cpp
+++ b/src/tbf.cpp
@@ -232,6 +232,9 @@
 	m_rlc.init();
 	m_llc.init();
 
+	/* HACK HACK HACK */
+	sched_pkt_acc_req = NULL;
+
 	m_name_buf[0] = '\0';
 }
 
diff --git a/src/tbf.h b/src/tbf.h
index 9545385..d103941 100644
--- a/src/tbf.h
+++ b/src/tbf.h
@@ -314,6 +314,9 @@
 
 	struct rate_ctr_group *m_ctrs;
 
+	/* HACK HACK HACK */
+	struct msgb *sched_pkt_acc_req;
+
 protected:
 	gprs_rlcmac_bts *bts_data() const;
 	void enable_egprs();