aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Couzens <lynxis@fe80.eu>2021-08-06 19:50:09 +0200
committerAlexander Couzens <lynxis@fe80.eu>2021-08-06 20:06:14 +0200
commitc66e348818d05496ae11c263ea8d021ef5a4e6ce (patch)
tree5cd2cdb660e100a82d69aa7ea7138738c8a6c389
parent0027f218b1c19d3628f40db242f7b0c6526a71a7 (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..ca8de19b 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, GPRS_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 fb84651d..3ee2e6f5 100644
--- a/src/gb/gprs_ns2_internal.h
+++ b/src/gb/gprs_ns2_internal.h
@@ -332,6 +332,7 @@ enum gprs_ns2_sns_event {
GPRS_SNS_EV_RX_CHANGE_WEIGHT,
GPRS_SNS_EV_RX_ACK, /*!< Rx of SNS-ACK (response to ADD/DELETE/CHG_WEIGHT */
GPRS_SNS_EV_REQ_NO_NSVC, /*!< no more NS-VC remaining (all dead) */
+ GPRS_SNS_EV_REQ_FREE_NSVCS, /*!< free all NS-VCs */
GPRS_SNS_EV_REQ_NSVC_ALIVE, /*!< a NS-VC became alive */
GPRS_SNS_EV_REQ_ADD_BIND, /*!< add a new local bind to this NSE */
GPRS_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 aee37fa9..f38a60dd 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[] = {
{ GPRS_SNS_EV_RX_ACK, "RX_ACK" },
{ GPRS_SNS_EV_RX_CHANGE_WEIGHT, "RX_CHANGE_WEIGHT" },
{ GPRS_SNS_EV_REQ_NO_NSVC, "REQ_NO_NSVC" },
+ { GPRS_SNS_EV_REQ_FREE_NSVCS, "REQ_FREE_NSVCS" },
{ GPRS_SNS_EV_REQ_NSVC_ALIVE, "REQ_NSVC_ALIVE"},
{ GPRS_SNS_EV_REQ_ADD_BIND, "REQ_ADD_BIND"},
{ GPRS_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 GPRS_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 GPRS_SNS_EV_REQ_FREE_NSVCS:
case GPRS_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(GPRS_SNS_EV_REQ_NO_NSVC) |
+ S(GPRS_SNS_EV_REQ_FREE_NSVCS) |
S(GPRS_SNS_EV_REQ_SELECT_ENDPOINT) |
S(GPRS_SNS_EV_REQ_ADD_BIND) |
S(GPRS_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 GPRS_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(GPRS_SNS_EV_RX_SIZE) |
S(GPRS_SNS_EV_REQ_NO_NSVC) |
+ S(GPRS_SNS_EV_REQ_FREE_NSVCS) |
S(GPRS_SNS_EV_REQ_ADD_BIND) |
S(GPRS_SNS_EV_REQ_DELETE_BIND),
.allstate_action = ns2_sns_st_all_action_sgsn,