aboutsummaryrefslogtreecommitdiffstats
path: root/src/gb
diff options
context:
space:
mode:
Diffstat (limited to 'src/gb')
-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,