aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@osmocom.org>2021-01-18 14:58:51 +0100
committerHarald Welte <laforge@osmocom.org>2021-01-18 16:11:33 +0100
commit3221f878ee1970bbad6e51162516932318f7a22f (patch)
tree8265670aa07af2405cb490cb7be5549b746831e8
parent603f404e41a95e20d39ee64b649c8c19777caa8f (diff)
ns2: delay NS_AFF_CAUSE_RECOVERY until NS-VC for data + sig are unblocked
Right now we end up in situations where only a NS-VC for data (BVCI != 0) becomes unblocked, but the BSSGP and/or user application code is notified that the NSE has recovered. In the case of osmo-gbproxy, this will trigger a BVC-RESET on the BVCI=0, but that obviously only works if the sig_weight > 0... Closes: OS#4956 Change-Id: I933ee3969c052394d61ec6cf8c7c21d17957d9ab
-rw-r--r--src/gb/gprs_ns2.c27
-rw-r--r--src/gb/gprs_ns2_internal.h6
2 files changed, 17 insertions, 16 deletions
diff --git a/src/gb/gprs_ns2.c b/src/gb/gprs_ns2.c
index 7c517aad..dc8ad8e5 100644
--- a/src/gb/gprs_ns2.c
+++ b/src/gb/gprs_ns2.c
@@ -1121,13 +1121,18 @@ int ns2_recv_vc(struct gprs_ns2_vc *nsvc,
void ns2_nse_data_sum(struct gprs_ns2_nse *nse)
{
struct gprs_ns2_vc *nsvc;
+
nse->nsvc_count = 0;
+ nse->sum_data_weight = 0;
+ nse->sum_sig_weight = 0;
llist_for_each_entry(nsvc, &nse->nsvc, list) {
if (!gprs_ns2_vc_is_unblocked(nsvc))
continue;
nse->nsvc_count++;
+ nse->sum_data_weight += nsvc->data_weight;
+ nse->sum_sig_weight += nsvc->sig_weight;
}
}
@@ -1137,35 +1142,25 @@ void ns2_nse_data_sum(struct gprs_ns2_nse *nse)
void ns2_nse_notify_unblocked(struct gprs_ns2_vc *nsvc, bool unblocked)
{
struct gprs_ns2_nse *nse = nsvc->nse;
- struct gprs_ns2_vc *tmp;
ns2_nse_data_sum(nse);
if (unblocked == nse->alive)
return;
- if (unblocked) {
- /* this is the first unblocked NSVC on an unavailable NSE */
+ /* wait until both data_weight and sig_weight are != 0 before declaring NSE as alive */
+ if (unblocked && nse->sum_data_weight && nse->sum_sig_weight) {
nse->alive = true;
ns2_prim_status_ind(nse, NULL, 0, NS_AFF_CAUSE_RECOVERY);
nse->first = false;
return;
}
- /* check if there are any remaining alive vcs */
- llist_for_each_entry(tmp, &nse->nsvc, list) {
- if (tmp == nsvc)
- continue;
-
- if (gprs_ns2_vc_is_unblocked(tmp)) {
- /* there is at least one remaining alive NSVC */
- return;
- }
+ if (nse->alive && (nse->sum_data_weight == 0 || nse->sum_sig_weight == 0)) {
+ /* nse became unavailable */
+ nse->alive = false;
+ ns2_prim_status_ind(nse, NULL, 0, NS_AFF_CAUSE_FAILURE);
}
-
- /* nse became unavailable */
- nse->alive = false;
- ns2_prim_status_ind(nse, NULL, 0, NS_AFF_CAUSE_FAILURE);
}
/*! Create a new GPRS NS instance
diff --git a/src/gb/gprs_ns2_internal.h b/src/gb/gprs_ns2_internal.h
index 5dbc349f..5404ed36 100644
--- a/src/gb/gprs_ns2_internal.h
+++ b/src/gb/gprs_ns2_internal.h
@@ -136,6 +136,12 @@ struct gprs_ns2_nse {
enum gprs_ns2_dialect dialect;
struct osmo_fsm_inst *bss_sns_fi;
+
+ /*! sum of all the data weight of _active_ NS-VCs */
+ uint32_t sum_data_weight;
+
+ /*! sum of all the signalling weight of _active_ NS-VCs */
+ uint32_t sum_sig_weight;
};
/*! Structure representing a single NS-VC */