gprs-ns: Fix reset state handling
Currently the NS-VC's state is updated from within gprs_ns_tx_reset,
which can lead to an inconsistent state when the RESET_ACK is lost.
In this state, the NSE_S_RESET bit is set but the Tns-reset timer is
not started.
This patch moves the state update into gprs_nsvc_reset. This way, the
state flags are consistent with the timer.
Addresses:
SGSN -> BSS NS_ALIVE
BSS -> SGSN NS_ALIVE_ACK
BSS -> SGSN BVC_RESET
SGSN -> BSS NS_STATUS, Cause: NS-VC blocked, NS VCI: 0x65
and there is no BSS->SGSN NS_ALIVE
Ticket: OW#1213
Sponsored-by: On-Waves ehf
diff --git a/src/gb/gprs_ns.c b/src/gb/gprs_ns.c
index cf7adaf..65d0494 100644
--- a/src/gb/gprs_ns.c
+++ b/src/gb/gprs_ns.c
@@ -348,8 +348,6 @@
LOGP(DNS, LOGL_INFO, "NSEI=%u Tx NS RESET (NSVCI=%u, cause=%s)\n",
nsvc->nsei, nsvc->nsvci, gprs_ns_cause_str(cause));
- nsvc->state |= NSE_S_RESET;
-
msg->l2h = msgb_put(msg, sizeof(*nsh));
nsh = (struct gprs_ns_hdr *) msg->l2h;
nsh->pdu_type = NS_PDUT_RESET;
@@ -1250,8 +1248,8 @@
* and should send a NS-RESET to make sure everything recovers
* fine. */
if ((*nsvc)->state == NSE_S_BLOCKED)
- rc = gprs_ns_tx_reset((*nsvc), NS_CAUSE_PDU_INCOMP_PSTATE);
- else
+ rc = gprs_nsvc_reset((*nsvc), NS_CAUSE_PDU_INCOMP_PSTATE);
+ else if (!((*nsvc)->state & NSE_S_RESET))
rc = gprs_ns_tx_alive_ack(*nsvc);
break;
case NS_PDUT_ALIVE_ACK:
@@ -1503,7 +1501,8 @@
nsvc->nsei);
/* Mark NS-VC locally as blocked and dead */
- nsvc->state = NSE_S_BLOCKED;
+ nsvc->state = NSE_S_BLOCKED | NSE_S_RESET;
+
/* Send NS-RESET PDU */
rc = gprs_ns_tx_reset(nsvc, cause);
if (rc < 0) {