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
This commit is contained in:
Alexander Couzens 2021-08-06 19:50:09 +02:00
parent a27078266a
commit 83f06cea0a
3 changed files with 18 additions and 3 deletions

View File

@ -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);
}
}
}

View File

@ -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 */

View File

@ -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,