gprs_ns2: Actually start Tns-test after SNS-CONFIG creates NS-VC

the previous commit fixed the state transition, but also caused
neither Tns-alive nor Tns-test to run

Change-Id: I07ea3fd5cec3d4acf4051930a1a3c746d6fd597c
diff --git a/src/gb/gprs_ns2_vc_fsm.c b/src/gb/gprs_ns2_vc_fsm.c
index 65248ea..f4d88f4 100644
--- a/src/gb/gprs_ns2_vc_fsm.c
+++ b/src/gb/gprs_ns2_vc_fsm.c
@@ -143,19 +143,38 @@
 	return priv->nsvc->nse->nsi;
 }
 
-static void start_test_procedure(struct gprs_ns2_vc_priv *priv)
+/* Start the NS-TEST procedure, either with transmitting a tx_alive,
+ * (start_tx_alive==true) or with starting tns-test */
+static void start_test_procedure(struct osmo_fsm_inst *fi, bool start_tx_alive)
 {
+	struct gprs_ns2_vc_priv *priv = fi->priv;
 	struct gprs_ns2_inst *nsi = priv->nsvc->nse->nsi;
+	unsigned int tout_idx;
 
-	if (osmo_timer_pending(&priv->alive.timer))
-		return;
+	if (osmo_timer_pending(&priv->alive.timer)) {
+		if (start_tx_alive) {
+			if (priv->alive.mode == NS_TOUT_TNS_ALIVE)
+				return;
+		} else {
+			if (priv->alive.mode == NS_TOUT_TNS_TEST)
+				return;
+		}
+	}
 
-	priv->alive.mode = NS_TOUT_TNS_ALIVE;
 	priv->alive.N = 0;
 
-	osmo_clock_gettime(CLOCK_MONOTONIC, &priv->alive.timer_started);
-	ns2_tx_alive(priv->nsvc);
-	osmo_timer_schedule(&priv->alive.timer, nsi->timeout[NS_TOUT_TNS_ALIVE], 0);
+	if (start_tx_alive) {
+		priv->alive.mode = NS_TOUT_TNS_ALIVE;
+		osmo_clock_gettime(CLOCK_MONOTONIC, &priv->alive.timer_started);
+		ns2_tx_alive(priv->nsvc);
+		tout_idx = NS_TOUT_TNS_ALIVE;
+	} else {
+		priv->alive.mode = NS_TOUT_TNS_TEST;
+		tout_idx = NS_TOUT_TNS_TEST;
+	}
+	LOGPFSML(fi, LOGL_DEBUG, "Starting Tns-%s of %u seconds\n",
+		 tout_idx == NS_TOUT_TNS_ALIVE ? "alive" : "test", nsi->timeout[tout_idx]);
+	osmo_timer_schedule(&priv->alive.timer, nsi->timeout[tout_idx], 0);
 }
 
 static void stop_test_procedure(struct gprs_ns2_vc_priv *priv)
@@ -163,6 +182,7 @@
 	osmo_timer_del(&priv->alive.timer);
 }
 
+/* how many milliseconds have expired since the last alive timer start? */
 static int alive_timer_elapsed_ms(struct gprs_ns2_vc_priv *priv)
 {
 	struct timespec now, elapsed;
@@ -174,6 +194,7 @@
 	return elapsed.tv_sec * 1000 + (elapsed.tv_nsec / 1000000);
 }
 
+/* we just received a NS-ALIVE-ACK; re-schedule after Tns-test */
 static void recv_test_procedure(struct osmo_fsm_inst *fi)
 {
 	struct gprs_ns2_vc_priv *priv = fi->priv;
@@ -326,7 +347,7 @@
 		ns2_tx_unblock(priv->nsvc);
 	}
 
-	start_test_procedure(priv);
+	start_test_procedure(fi, true);
 }
 
 static void ns2_st_blocked(struct osmo_fsm_inst *fi, uint32_t event, void *data)
@@ -392,6 +413,12 @@
 	priv->accept_unitdata = true;
 	ns2_nse_notify_unblocked(nsvc, true);
 	ns2_prim_status_ind(nse, nsvc, 0, GPRS_NS2_AFF_CAUSE_VC_RECOVERY);
+
+	/* the closest interpretation of the spec would start Tns-test here first,
+	 * and only send a NS-ALIVE after Tns-test has expired (i.e. setting the
+	 * second argument to 'false'.  However, being quick in detecting unavailability
+	 * of a NS-VC seems like a good idea */
+	start_test_procedure(fi, true);
 }
 
 static void ns2_st_unblocked(struct osmo_fsm_inst *fi, uint32_t event, void *data)
@@ -431,9 +458,8 @@
 	if (old_state != GPRS_NS2_ST_RECOVERING)
 		priv->N = 0;
 
-	ns2_tx_alive(priv->nsvc);
 	ns2_nse_notify_unblocked(priv->nsvc, false);
-	start_test_procedure(priv);
+	start_test_procedure(fi, true);
 }
 
 static const struct osmo_fsm_state ns2_vc_states[] = {