aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Couzens <lynxis@fe80.eu>2021-08-06 19:50:09 +0200
committerAlexander Couzens <lynxis@fe80.eu>2021-09-04 00:00:48 +0200
commit83f06cea0a69d753ee64a44701f0292b4cfbeb86 (patch)
tree7c5f0de05547c888b4342eca52dcb2eca2a441f6
parenta27078266af5150076030f769f81de9faf2d8c65 (diff)
gprs_ns2: use an event to free the nsvscs when using SNS
Otherwise there could be recursive loop when free'ing NSVCs which in the end create an event which the SNS want to free the NSVCs a second time Change-Id: Ie99ba5fe8a84519fe8a8c0abdf875606715ab7f6
-rw-r--r--src/gb/gprs_ns2.c8
-rw-r--r--src/gb/gprs_ns2_internal.h1
-rw-r--r--src/gb/gprs_ns2_sns.c12
3 files changed, 18 insertions, 3 deletions
diff --git a/src/gb/gprs_ns2.c b/src/gb/gprs_ns2.c
index 45cdfcc1..83a8ca07 100644
--- a/src/gb/gprs_ns2.c
+++ b/src/gb/gprs_ns2.c
@@ -674,8 +674,12 @@ void gprs_ns2_free_nsvcs(struct gprs_ns2_nse *nse)
if (!nse || nse->freed)
return;
- llist_for_each_entry_safe(nsvc, tmp, &nse->nsvc, list) {
- gprs_ns2_free_nsvc(nsvc);
+ if (nse->bss_sns_fi) {
+ osmo_fsm_inst_dispatch(nse->bss_sns_fi, NS2_SNS_EV_REQ_FREE_NSVCS, NULL);
+ } else {
+ llist_for_each_entry_safe(nsvc, tmp, &nse->nsvc, list) {
+ gprs_ns2_free_nsvc(nsvc);
+ }
}
}
diff --git a/src/gb/gprs_ns2_internal.h b/src/gb/gprs_ns2_internal.h
index 60962639..d2407f66 100644
--- a/src/gb/gprs_ns2_internal.h
+++ b/src/gb/gprs_ns2_internal.h
@@ -332,6 +332,7 @@ enum ns2_sns_event {
NS2_SNS_EV_RX_CHANGE_WEIGHT,
NS2_SNS_EV_RX_ACK, /*!< Rx of SNS-ACK (response to ADD/DELETE/CHG_WEIGHT */
NS2_SNS_EV_REQ_NO_NSVC, /*!< no more NS-VC remaining (all dead) */
+ NS2_SNS_EV_REQ_FREE_NSVCS, /*!< free all NS-VCs */
NS2_SNS_EV_REQ_NSVC_ALIVE, /*!< a NS-VC became alive */
NS2_SNS_EV_REQ_ADD_BIND, /*!< add a new local bind to this NSE */
NS2_SNS_EV_REQ_DELETE_BIND, /*!< remove a local bind from this NSE */
diff --git a/src/gb/gprs_ns2_sns.c b/src/gb/gprs_ns2_sns.c
index 1b2864ef..e96f6b3f 100644
--- a/src/gb/gprs_ns2_sns.c
+++ b/src/gb/gprs_ns2_sns.c
@@ -84,6 +84,7 @@ static const struct value_string gprs_sns_event_names[] = {
{ NS2_SNS_EV_RX_ACK, "RX_ACK" },
{ NS2_SNS_EV_RX_CHANGE_WEIGHT, "RX_CHANGE_WEIGHT" },
{ NS2_SNS_EV_REQ_NO_NSVC, "REQ_NO_NSVC" },
+ { NS2_SNS_EV_REQ_FREE_NSVCS, "REQ_FREE_NSVCS" },
{ NS2_SNS_EV_REQ_NSVC_ALIVE, "REQ_NSVC_ALIVE"},
{ NS2_SNS_EV_REQ_ADD_BIND, "REQ_ADD_BIND"},
{ NS2_SNS_EV_REQ_DELETE_BIND, "REQ_DELETE_BIND"},
@@ -1564,6 +1565,7 @@ static void ns2_sns_st_all_action_bss(struct osmo_fsm_inst *fi, uint32_t event,
{
struct ns2_sns_state *gss = (struct ns2_sns_state *) fi->priv;
struct gprs_ns2_nse *nse = nse_inst_from_fi(fi);
+ struct gprs_ns2_vc *nsvc, *nsvc2;
/* reset when receiving NS2_SNS_EV_REQ_NO_NSVC */
switch (event) {
@@ -1574,11 +1576,14 @@ static void ns2_sns_st_all_action_bss(struct osmo_fsm_inst *fi, uint32_t event,
sns_failed(fi, "no remaining NSVC, resetting SNS FSM");
break;
+ case NS2_SNS_EV_REQ_FREE_NSVCS:
case NS2_SNS_EV_REQ_SELECT_ENDPOINT:
/* tear down previous state
* gprs_ns2_free_nsvcs() will trigger NO_NSVC, prevent this from triggering a reselection */
gss->reselection_running = true;
- gprs_ns2_free_nsvcs(nse);
+ llist_for_each_entry_safe(nsvc, nsvc2, &nse->nsvc, list) {
+ gprs_ns2_free_nsvc(nsvc);
+ }
ns2_clear_elems(&gss->local);
ns2_clear_elems(&gss->remote);
@@ -1613,6 +1618,7 @@ static struct osmo_fsm gprs_ns2_sns_bss_fsm = {
.states = ns2_sns_bss_states,
.num_states = ARRAY_SIZE(ns2_sns_bss_states),
.allstate_event_mask = S(NS2_SNS_EV_REQ_NO_NSVC) |
+ S(NS2_SNS_EV_REQ_FREE_NSVCS) |
S(NS2_SNS_EV_REQ_SELECT_ENDPOINT) |
S(NS2_SNS_EV_REQ_ADD_BIND) |
S(NS2_SNS_EV_REQ_DELETE_BIND),
@@ -2329,6 +2335,9 @@ static void ns2_sns_st_all_action_sgsn(struct osmo_fsm_inst *fi, uint32_t event,
if (flag & 1)
osmo_fsm_inst_state_chg(fi, GPRS_SNS_ST_SGSN_WAIT_CONFIG, 0, 0);
break;
+ case NS2_SNS_EV_REQ_FREE_NSVCS:
+ sns_failed(fi, "On user request to free all NSVCs");
+ break;
default:
ns2_sns_st_all_action(fi, event, data);
break;
@@ -2341,6 +2350,7 @@ static struct osmo_fsm gprs_ns2_sns_sgsn_fsm = {
.num_states = ARRAY_SIZE(ns2_sns_sgsn_states),
.allstate_event_mask = S(NS2_SNS_EV_RX_SIZE) |
S(NS2_SNS_EV_REQ_NO_NSVC) |
+ S(NS2_SNS_EV_REQ_FREE_NSVCS) |
S(NS2_SNS_EV_REQ_ADD_BIND) |
S(NS2_SNS_EV_REQ_DELETE_BIND),
.allstate_action = ns2_sns_st_all_action_sgsn,