aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gprs_bssgp_pcu.cpp45
-rw-r--r--src/gprs_bssgp_pcu.h1
-rw-r--r--src/pcu_l1_if.cpp35
-rw-r--r--src/pcuif_proto.h3
4 files changed, 84 insertions, 0 deletions
diff --git a/src/gprs_bssgp_pcu.cpp b/src/gprs_bssgp_pcu.cpp
index da1d26c1..a4f77b9f 100644
--- a/src/gprs_bssgp_pcu.cpp
+++ b/src/gprs_bssgp_pcu.cpp
@@ -24,9 +24,11 @@
#include <bts.h>
#include <tbf.h>
#include <decoding.h>
+#include <pcuif_proto.h>
#define BSSGP_TIMER_T1 30 /* Guards the (un)blocking procedures */
#define BSSGP_TIMER_T2 30 /* Guards the reset procedure */
+#define BSSGP_TIMER_T3 5 /* Reset procedure status polling timer*/
/* Tuning parameters for BSSGP flow control */
#define FC_DEFAULT_LIFE_TIME_SECS 10 /* experimental value, 10s */
@@ -44,6 +46,7 @@ extern void *tall_pcu_ctx;
extern uint16_t spoof_mcc, spoof_mnc;
static void bvc_timeout(void *_priv);
+static void bssgp_timeout_cb(void *_priv);
static int parse_imsi(struct tlv_parsed *tp, char *imsi)
{
@@ -507,6 +510,9 @@ static int nsvc_signal_cb(unsigned int subsys, unsigned int signal,
case S_NS_ALIVE_EXP:
LOGP(DPCU, LOGL_NOTICE, "Tns alive expired too often, "
"re-starting RESET procedure\n");
+ memcpy(alarm_sig_data.spare, &the_pcu.nsvc->nsvci, sizeof(uint16_t));
+ osmo_signal_dispatch(SS_L_GLOBAL, S_PCU_NM_FAIL_NSVC_ALARM, &alarm_sig_data);
+
gprs_ns_reconnect(nssd->nsvc);
break;
}
@@ -780,6 +786,9 @@ static void bvc_timeout(void *_priv)
return;
}
+ /* Cancel any pending BSSGP timer on successful of BVCI reset */
+ osmo_timer_del(&the_pcu.bssgp_timer);
+
if (!the_pcu.bvc_unblocked) {
LOGP(DBSSGP, LOGL_INFO, "Sending unblock on BVCI %d\n",
the_pcu.bctx->bvci);
@@ -816,6 +825,13 @@ int gprs_ns_reconnect(struct gprs_nsvc *nsvc)
return -EIO;
}
+ /* Cancel any existing BSSGP timer */
+ osmo_timer_del(&the_pcu.bssgp_timer);
+
+ /* start BSSGP timer */
+ the_pcu.bssgp_timer.cb = bssgp_timeout_cb;
+ osmo_timer_schedule(&the_pcu.bssgp_timer, BSSGP_TIMER_T3, 0);
+
return 0;
}
@@ -884,6 +900,12 @@ struct gprs_bssgp_pcu *gprs_bssgp_create_and_connect(struct gprs_rlcmac_bts *bts
the_pcu.bvc_timer.cb = bvc_timeout;
+ /* Cancel any existing BSSGP timer */
+ osmo_timer_del(&the_pcu.bssgp_timer);
+
+ /* Start BSSGP timer */
+ the_pcu.bssgp_timer.cb = bssgp_timeout_cb;
+ osmo_timer_schedule(&the_pcu.bssgp_timer, BSSGP_TIMER_T3, 0);
return &the_pcu;
}
@@ -946,3 +968,26 @@ void gprs_bssgp_update_queue_delay(const struct timeval *tv_recv,
the_pcu.queue_delay_count += 1;
}
+
+static void bssgp_timeout_cb(void *_priv) {
+
+ LOGP(DBSSGP, LOGL_DEBUG, "BSSGP timer expired, NSVC state=%x, restart BSSGP timer\n", the_pcu.nsvc->state);
+
+ if (the_pcu.nsvc->state & NSE_S_BLOCKED) {
+ LOGP(DBSSGP, LOGL_DEBUG, "PCU: Tx NSVC BLOCKED failure alarm\n");
+ memcpy(alarm_sig_data.spare, &the_pcu.nsvc->nsvci, sizeof(uint16_t));
+ osmo_signal_dispatch(SS_L_GLOBAL, S_PCU_NM_FAIL_UNBLK_NSVC_ALARM, &alarm_sig_data);
+ }
+
+ if (the_pcu.nsvc->state & NSE_S_RESET) {
+ LOGP(DBSSGP, LOGL_DEBUG, "PCU: Tx NSVC RESET failure alarm\n");
+ memcpy(alarm_sig_data.spare, &the_pcu.nsvc->nsvci, sizeof(uint16_t));
+ osmo_signal_dispatch(SS_L_GLOBAL, S_PCU_NM_FAIL_RST_NSVC_ALARM, &alarm_sig_data);
+ }
+
+ /* Cancel any existing BSSGP timer */
+ osmo_timer_del(&the_pcu.bssgp_timer);
+
+ /* restart BSSGP timer */
+ osmo_timer_schedule(&the_pcu.bssgp_timer, BSSGP_TIMER_T3, 0);
+}
diff --git a/src/gprs_bssgp_pcu.h b/src/gprs_bssgp_pcu.h
index bb449034..4b956850 100644
--- a/src/gprs_bssgp_pcu.h
+++ b/src/gprs_bssgp_pcu.h
@@ -51,6 +51,7 @@ struct gprs_bssgp_pcu {
struct gprs_rlcmac_bts *bts;
struct osmo_timer_list bvc_timer;
+ struct osmo_timer_list bssgp_timer;
int nsvc_unblocked;
diff --git a/src/pcu_l1_if.cpp b/src/pcu_l1_if.cpp
index 7308fa1f..3fb00f34 100644
--- a/src/pcu_l1_if.cpp
+++ b/src/pcu_l1_if.cpp
@@ -624,6 +624,7 @@ static int handle_pcu_fail_evt_rep_sig(unsigned int subsys, unsigned int signal,
int rc = 0;
unsigned int res;
char log_msg[100];
+ uint16_t nscvi;
if (subsys != SS_L_GLOBAL)
return 0;
@@ -715,6 +716,40 @@ static int handle_pcu_fail_evt_rep_sig(unsigned int subsys, unsigned int signal,
sig_data->add_text);
break;
+ case S_PCU_NM_FAIL_NSVC_ALARM:
+ memcpy(&nscvi, sig_data->spare, sizeof(uint16_t));
+ snprintf(log_msg, 100, "PCU: NS-VC %d failure\n", nscvi);
+ sig_data->add_text = &log_msg[0];
+
+ rc = pcu_tx_nm_fail_evt(NM_EVT_COMM_FAIL,
+ NM_SEVER_MAJOR,
+ NM_PCAUSE_T_MANUF,
+ PCU_NM_EVT_CAUSE_CRIT_NSVC_FAIL,
+ sig_data->add_text);
+ break;
+
+ case S_PCU_NM_FAIL_RST_NSVC_ALARM:
+ memcpy(&nscvi, sig_data->spare, sizeof(uint16_t));
+ snprintf(log_msg, 100, "PCU: NS-VC %d reset failure\n", nscvi);
+ sig_data->add_text = &log_msg[0];
+ rc = pcu_tx_nm_fail_evt(NM_EVT_COMM_FAIL,
+ NM_SEVER_MAJOR,
+ NM_PCAUSE_T_MANUF,
+ PCU_NM_EVT_CAUSE_CRIT_NSVC_RST_FAIL,
+ sig_data->add_text);
+ break;
+
+ case S_PCU_NM_FAIL_UNBLK_NSVC_ALARM:
+ memcpy(&nscvi, sig_data->spare, sizeof(uint16_t));
+ snprintf(log_msg, 100, "PCU: NS-VC %d unblock failure\n", nscvi);
+ sig_data->add_text = &log_msg[0];
+ rc = pcu_tx_nm_fail_evt(NM_EVT_COMM_FAIL,
+ NM_SEVER_MAJOR,
+ NM_PCAUSE_T_MANUF,
+ PCU_NM_EVT_CAUSE_CRIT_NSVC_UNBLK_FAIL,
+ sig_data->add_text);
+ break;
+
default:
break;
}
diff --git a/src/pcuif_proto.h b/src/pcuif_proto.h
index e4604ba7..85a9040e 100644
--- a/src/pcuif_proto.h
+++ b/src/pcuif_proto.h
@@ -57,6 +57,9 @@ extern "C" {
/* NuRAN Wireless manufacture-defined alarm causes */
enum pcu_nm_event_causes {
/* Critical causes */
+ PCU_NM_EVT_CAUSE_CRIT_NSVC_FAIL = 0x3310,
+ PCU_NM_EVT_CAUSE_CRIT_NSVC_RST_FAIL = 0x3311,
+ PCU_NM_EVT_CAUSE_CRIT_NSVC_UNBLK_FAIL = 0x3312,
PCU_NM_EVT_CAUSE_CRIT_OPEN_L1_FAIL = 0x333b,
PCU_NM_EVT_CAUSE_CRIT_OPEN_PDCH_FAIL = 0x3411,
PCU_NM_EVT_CAUSE_CRIT_BAD_PCU_IF_VER = 0x3415,