From 3221f878ee1970bbad6e51162516932318f7a22f Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 18 Jan 2021 14:58:51 +0100 Subject: 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 --- src/gb/gprs_ns2.c | 27 +++++++++++---------------- src/gb/gprs_ns2_internal.h | 6 ++++++ 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 */ -- cgit v1.2.3