llc: Add put_dummy_frame to create an LLC dummy command

The LLC dummy command is needed for RLC block stuffing, e.g. when a
TBF should be kept open if no LLC data is available. The RLC block
headers do not support stuffing, only the last block of a TBF can be
used partially. LLC dummy commands are discarded by the receiver
immediately, because the have an invalid FCS checksum.

This commit adds the function put_dummy_frame, which puts a LLC dummy
command into the frame buffer. The requested length is given as an
argument, but the real length might be adjusted according to the
specification (see GSM 44.064, 6.4.2.2).

Sponsored-by: On-Waves ehf
diff --git a/src/llc.cpp b/src/llc.cpp
index 2d295f8..b160961 100644
--- a/src/llc.cpp
+++ b/src/llc.cpp
@@ -48,6 +48,26 @@
 	msgb_enqueue(&queue, llc_msg);
 }
 
+/* Put an Unconfirmed Information (UI) Dummy command, see GSM 44.064, 6.4.2.2 */
+void gprs_llc::put_dummy_frame(size_t req_len)
+{
+	/* The shortest dummy command (the spec requests at least 6 octets) */
+	static const uint8_t llc_dummy_command[] = {
+		0x43, 0xc0, 0x01, 0x2b, 0x2b, 0x2b
+	};
+	static const int max_dummy_command_len = 79;
+
+	put_frame(llc_dummy_command, sizeof(llc_dummy_command));
+
+	if (req_len > max_dummy_command_len)
+		req_len = max_dummy_command_len;
+
+	/* Add further stuffing, if the requested length exceeds the minimum
+	 * dummy command length */
+	while (m_length < req_len)
+		frame[m_length++] = 0x2b;
+}
+
 void gprs_llc::put_frame(const uint8_t *data, size_t len)
 {
 	/* only put frames when we are empty */