diff options
author | Harald Welte <laforge@gnumonks.org> | 2016-11-14 14:54:41 +0100 |
---|---|---|
committer | Neels Hofmeyr <nhofmeyr@sysmocom.de> | 2016-12-08 01:40:21 +0100 |
commit | 8e358d7ccfd4a3663259e427e05a1b54091f1e00 (patch) | |
tree | 4e932707da5c07960af0f51c5b50c5cb7f7b2a49 | |
parent | 1db9a0bc5de21d36cc42b5fd5f26f11a3e1d1329 (diff) |
WIP: attempt at a subscr_conn_fsmneels/vlr_subscr_conn_fsm
Change-Id: Ie42cb4c286c413c8acbc0b235b4f44fd74806a97
-rw-r--r-- | openbsc/src/libbsc/bsc_api.c | 4 | ||||
-rw-r--r-- | openbsc/src/libmsc/Makefile.am | 1 | ||||
-rw-r--r-- | openbsc/src/libmsc/subscr_conn_fsm.c | 132 |
3 files changed, 137 insertions, 0 deletions
diff --git a/openbsc/src/libbsc/bsc_api.c b/openbsc/src/libbsc/bsc_api.c index 395002ada..427005402 100644 --- a/openbsc/src/libbsc/bsc_api.c +++ b/openbsc/src/libbsc/bsc_api.c @@ -247,6 +247,10 @@ struct gsm_subscriber_connection *bsc_subscr_con_allocate(struct gsm_lchan *lcha conn = talloc_zero(net, struct gsm_subscriber_connection); if (!conn) return NULL; + if (!msc_create_conn_fsm(conn, NULL)) { + talloc_free(conn); + return NULL; + } conn->network = net; conn->lchan = lchan; diff --git a/openbsc/src/libmsc/Makefile.am b/openbsc/src/libmsc/Makefile.am index 9d966dbc1..ab5ade059 100644 --- a/openbsc/src/libmsc/Makefile.am +++ b/openbsc/src/libmsc/Makefile.am @@ -35,6 +35,7 @@ libmsc_a_SOURCES = \ rrlp.c \ silent_call.c \ sms_queue.c \ + subscr_conn_fsm.c \ token_auth.c \ ussd.c \ vty_interface_layer3.c \ diff --git a/openbsc/src/libmsc/subscr_conn_fsm.c b/openbsc/src/libmsc/subscr_conn_fsm.c new file mode 100644 index 000000000..12756172c --- /dev/null +++ b/openbsc/src/libmsc/subscr_conn_fsm.c @@ -0,0 +1,132 @@ +/* (C) 2016 by Harald Welte <laforge@gnumonks.org> + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#include <osmocom/core/fsm.h> + +#include <openbsc/bsc_api.h> +#include <openbsc/debug.h> +#include <openbsc/vlr.h> +#include <openbsc/osmo_msc.h> + +#define S(x) (1 << (x)) + +/* This FSM primarily exists as a root/anchor to the various other FSM's + * that we are starting during the life time of a subscriber_connection. + * By having this FSM as part of the subscriber_connection, the other + * FSMs can interact naturally with it, i.e. signal it on child + * termination, keep a linked list of all child FSMs, ... */ + +enum subscr_conn_fsm_state { + /* Initial state, most of its lifetime */ + SUB_CON_S_INIT, + /* Release has been initiated and is ongoing */ + SUB_CON_S_RELEASING, + /* Release completed, connection closed */ + SUB_CON_S_CLOSED, +}; + +static const struct value_string subscr_conn_fsm_event_names[] = { + { SUB_CON_E_LU_RES, "LU-RES" }, + { SUB_CON_E_PARQ_RES, "PROC-ARQ-RES" }, + { SUB_CON_E_MO_CLOSE, "MO-CLOSE" }, + { SUB_CON_E_CN_CLOSE, "CN-CLOSE" }, + { SUB_CON_E_CLOSE_CONF, "CLOSE-CONF" }, + { 0, NULL } +}; + +static void subscr_conn_fsm_f_init(struct osmo_fsm_inst *fi, + uint32_t event, void *data) +{ + struct gsm_subscriber_connection *conn = fi->priv; + + switch (event) { + case SUB_CON_E_LU_RES: + /* LU has completed, drop ref count */ + subscr_con_put(conn); + break; + case SUB_CON_E_PARQ_RES: + /* Proc Acc Req has completed, drop ref count */ + subscr_con_put(conn); + break; + case SUB_CON_E_MO_CLOSE: + case SUB_CON_E_CN_CLOSE: + /* TODO: move msc_release_connection() here */ + msc_release_connection(conn); + osmo_fsm_inst_state_chg(fi, SUB_CON_S_RELEASING, 0, 0); + break; + } +} + +static void subscr_conn_fsm_f_releasing(struct osmo_fsm_inst *fi, + uint32_t event, void *data) +{ + struct gsm_subscriber_connection *conn = fi->priv; + OSMO_ASSERT(event == SUB_CON_E_CLOSE_CONF); + + subscr_conn_free(conn); + osmo_fsm_inst_state_chg(fi, SUB_CON_S_CLOSED, 0, 0); + osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REGULAR, NULL); +} + +static const struct osmo_fsm_state subscr_conn_fsm_states[] = { + [SUB_CON_S_INIT] = { + .in_event_mask = S(SUB_CON_E_LU_RES) | + S(SUB_CON_E_PARQ_RES) | + S(SUB_CON_E_MO_CLOSE) | + S(SUB_CON_E_CN_CLOSE), + .out_state_mask = S(SUB_CON_S_RELEASING) | + S(SUB_CON_S_CLOSED), + .name = "INIT", + .action = subscr_conn_fsm_f_init, + }, + [SUB_CON_S_RELEASING] = { + .in_event_mask = S(SUB_CON_E_CLOSE_CONF), + .out_state_mask = S(SUB_CON_S_CLOSED), + .name = "RELEASING", + .action = subscr_conn_fsm_f_releasing, + }, + [SUB_CON_S_CLOSED] = { + .name = "CLOSED", + }, +}; + +static struct osmo_fsm subscr_conn_fsm = { + .name = "subscr_conn", + .states = subscr_conn_fsm_states, + .num_states = ARRAY_SIZE(subscr_conn_fsm_states), + .log_subsys = DMM, + .event_names = subscr_conn_fsm_event_names, +}; + +struct osmo_fsm_inst * +msc_create_conn_fsm(struct gsm_subscriber_connection *conn, + const char *id) +{ + struct osmo_fsm_inst *fi; + + OSMO_ASSERT(!conn->master_fsm); + + fi = osmo_fsm_inst_alloc(&subscr_conn_fsm, conn, conn, + LOGL_NOTICE, id); + if (!fi) + return NULL; + + fi->priv = conn; + conn->master_fsm = conn; +} |