gbproxy: Refactor local message generation

This patch adds und uses the function gbproxy_gsm48_to_peer() which
takes a GSM 04.08 message, encapsulates it in BSSGP and LLC, and
sends it to the BSS peer. This function increments vu_gen_tx_bss
which is now used instead of imsi_acq_retries to set the N(U) of the
outgoing message.

Since imsi_acq_retries isn't currently incremented before a Detach
Accept is generated, this patch also fixes the N(U) of such messages.

Sponsored-by: On-Waves ehf
diff --git a/openbsc/include/openbsc/gb_proxy.h b/openbsc/include/openbsc/gb_proxy.h
index c1882f3..1e8158b 100644
--- a/openbsc/include/openbsc/gb_proxy.h
+++ b/openbsc/include/openbsc/gb_proxy.h
@@ -10,6 +10,8 @@
 #include <sys/types.h>
 #include <regex.h>
 
+#define GBPROXY_INIT_VU_GEN_TX 256
+
 struct rate_ctr_group;
 struct gprs_gb_parse_context;
 struct tlv_parsed;
@@ -148,11 +150,12 @@
 
 	int imsi_acq_pending;
 	struct llist_head stored_msgs;
-	int imsi_acq_retries;
+	unsigned vu_gen_tx_bss;
 
 	int is_deregistered;
 
 	int imsi_matches;
+
 };
 
 
diff --git a/openbsc/src/gprs/gb_proxy.c b/openbsc/src/gprs/gb_proxy.c
index 867364d..3257f74 100644
--- a/openbsc/src/gprs/gb_proxy.c
+++ b/openbsc/src/gprs/gb_proxy.c
@@ -286,10 +286,8 @@
 	if (!link_info)
 		return 0;
 
-	if (link_info->imsi_acq_pending) {
+	if (link_info->imsi_acq_pending)
 		in_progress = 1;
-		link_info->imsi_acq_retries += 1;
-	}
 
 	gbproxy_link_info_discard_messages(link_info);
 	link_info->imsi_acq_pending = 0;
@@ -300,7 +298,7 @@
 static void gbproxy_reset_imsi_acquisition(struct gbproxy_link_info* link_info)
 {
 	gbproxy_restart_imsi_acquisition(link_info);
-	link_info->imsi_acq_retries = 0;
+	link_info->vu_gen_tx_bss = GBPROXY_INIT_VU_GEN_TX;
 }
 
 static void gbproxy_flush_stored_messages(struct gbproxy_peer *peer,
@@ -351,6 +349,26 @@
 	}
 }
 
+static int gbproxy_gsm48_to_peer(struct gbproxy_peer *peer,
+				 struct gbproxy_link_info* link_info,
+				 uint16_t bvci,
+				 struct msgb *msg /* Takes msg ownership */)
+{
+	int rc;
+
+	/* Workaround to avoid N(U) collisions and to enable a restart
+	 * of the IMSI acquisition procedure. This will work unless the
+	 * SGSN has an initial V(UT) within [256-32, 256+n_retries]
+	 * (see GSM 04.64, 8.4.2). */
+	gprs_push_llc_ui(msg, 0, GPRS_SAPI_GMM, link_info->vu_gen_tx_bss);
+	link_info->vu_gen_tx_bss = (link_info->vu_gen_tx_bss + 1) % 512;
+
+	gprs_push_bssgp_dl_unitdata(msg, link_info->tlli.current);
+	rc = gbprox_relay2peer(msg, peer, bvci);
+	msgb_free(msg);
+	return rc;
+}
+
 static void gbproxy_acquire_imsi(struct gbproxy_peer *peer,
 				 struct gbproxy_link_info* link_info,
 				 uint16_t bvci)
@@ -360,18 +378,7 @@
 	/* Send IDENT REQ */
 	idreq_msg = gsm48_msgb_alloc();
 	gprs_put_identity_req(idreq_msg, GSM_MI_TYPE_IMSI);
-	/* Workaround to avoid N(U) collisions and to enable a restart
-	 * of the IMSI acquisition procedure. This will work unless the
-	 * SGSN has an initial V(UT) within [256-32, 256+n_retries]
-	 * (see GSM 04.64, 8.4.2).
-	 * TODO: Check whether it is sensible to rely on this, it might
-	 * be an issue when P-TMSI patching is _not_ enabled and the SGSN
-	 * doesn't reset V(UT) after a detach. */
-	gprs_push_llc_ui(idreq_msg, 0, GPRS_SAPI_GMM,
-			 (link_info->imsi_acq_retries + 256) % 512);
-	gprs_push_bssgp_dl_unitdata(idreq_msg, link_info->tlli.current);
-	gbprox_relay2peer(idreq_msg, peer, bvci);
-	msgb_free(idreq_msg);
+	gbproxy_gsm48_to_peer(peer, link_info, bvci, idreq_msg);
 }
 
 static void gbproxy_tx_detach_acc(struct gbproxy_peer *peer,
@@ -383,11 +390,7 @@
 	/* Send DETACH ACC */
 	detacc_msg = gsm48_msgb_alloc();
 	gprs_put_mo_detach_acc(detacc_msg);
-	gprs_push_llc_ui(detacc_msg, 0, GPRS_SAPI_GMM,
-			 (link_info->imsi_acq_retries + 256) % 512);
-	gprs_push_bssgp_dl_unitdata(detacc_msg, link_info->tlli.current);
-	gbprox_relay2peer(detacc_msg, peer, bvci);
-	msgb_free(detacc_msg);
+	gbproxy_gsm48_to_peer(peer, link_info, bvci, detacc_msg);
 }
 
 /* Return != 0 iff msg still needs to be processed */
diff --git a/openbsc/src/gprs/gb_proxy_tlli.c b/openbsc/src/gprs/gb_proxy_tlli.c
index fae05ed..093d2b3 100644
--- a/openbsc/src/gprs/gb_proxy_tlli.c
+++ b/openbsc/src/gprs/gb_proxy_tlli.c
@@ -238,6 +238,8 @@
 	link_info->tlli.ptmsi = GSM_RESERVED_TMSI;
 	link_info->sgsn_tlli.ptmsi = GSM_RESERVED_TMSI;
 
+	link_info->vu_gen_tx_bss = GBPROXY_INIT_VU_GEN_TX;
+
 	INIT_LLIST_HEAD(&link_info->stored_msgs);
 
 	return link_info;
diff --git a/openbsc/tests/gbproxy/gbproxy_test.ok b/openbsc/tests/gbproxy/gbproxy_test.ok
index d0c9d61..406d320 100644
--- a/openbsc/tests/gbproxy/gbproxy_test.ok
+++ b/openbsc/tests/gbproxy/gbproxy_test.ok
@@ -3516,7 +3516,7 @@
 
 NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 24 (gprs_ns_sendmsg)
 MESSAGE to BSS at 0x01020304:1111, msg length 28
-00 00 10 02 00 80 00 de ad 00 50 20 16 82 02 58 0e 00 09 41 c4 05 08 06 00 29 4a 68 
+00 00 10 02 00 80 00 de ad 00 50 20 16 82 02 58 0e 00 09 41 c4 09 08 06 00 da 80 ca 
 
 result (DETACH REQ) = 0
 
@@ -3582,7 +3582,7 @@
 
 NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 24 (gprs_ns_sendmsg)
 MESSAGE to BSS at 0x01020304:1111, msg length 28
-00 00 10 02 00 80 00 de ad 00 50 20 16 82 02 58 0e 00 09 41 c4 05 08 06 00 29 4a 68 
+00 00 10 02 00 80 00 de ad 00 50 20 16 82 02 58 0e 00 09 41 c4 09 08 06 00 da 80 ca 
 
 result (DETACH REQ) = 0
 
@@ -5515,7 +5515,7 @@
 
 NS UNITDATA MESSAGE to BSS, BVCI 0x1002, msg length 24 (gprs_ns_sendmsg)
 MESSAGE to BSS at 0x01020304:1111, msg length 28
-00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 0e 00 09 41 c4 01 08 06 00 11 f5 c0 
+00 00 10 02 00 af e2 b7 00 00 50 20 16 82 02 58 0e 00 09 41 c4 05 08 06 00 29 4a 68 
 
 result (DETACH REQ (MO)) = 0