osmith submitted this change.

View Change

Approvals: Jenkins Builder: Verified pespin: Looks good to me, approved
Send RESET to MSC on start up

Automatically send RESET to the MSC as the BSCNAT starts up. Try it
again if it fails, in case the MSC was not started yet or if the SCCP
connection was not up yet (right now it does not seem possible to get
notified when the SCCP connection is up).

Related: SYS#5560
Related: https://osmocom.org/projects/osmo-bscnat/wiki/AoIP_OsmoBSCNAT#RESET
Change-Id: Icfec3ec0168c7040e88a536fa48da339349fb6cf
---
M include/osmocom/bsc_nat/bssap.h
M include/osmocom/bsc_nat/msc.h
M src/osmo-bsc-nat/Makefile.am
M src/osmo-bsc-nat/bsc_nat_fsm.c
M src/osmo-bsc-nat/bssap.c
M src/osmo-bsc-nat/msc.c
A src/osmo-bsc-nat/msc_fsm.c
7 files changed, 216 insertions(+), 19 deletions(-)

diff --git a/include/osmocom/bsc_nat/bssap.h b/include/osmocom/bsc_nat/bssap.h
index 996cb69..ca387c2 100644
--- a/include/osmocom/bsc_nat/bssap.h
+++ b/include/osmocom/bsc_nat/bssap.h
@@ -23,3 +23,5 @@

int bssap_handle_udt(struct bsc_nat_sccp_inst *sccp_inst, struct osmo_sccp_addr *addr, struct msgb *msgb,
unsigned int length);
+
+int bssap_tx_reset(struct bsc_nat_sccp_inst *sccp_inst, struct osmo_sccp_addr *addr);
diff --git a/include/osmocom/bsc_nat/msc.h b/include/osmocom/bsc_nat/msc.h
index 1f91de0..47b4d13 100644
--- a/include/osmocom/bsc_nat/msc.h
+++ b/include/osmocom/bsc_nat/msc.h
@@ -19,11 +19,13 @@

#pragma once

+#include <osmocom/core/fsm.h>
#include <osmocom/sigtran/sccp_sap.h>

struct msc {
struct llist_head list;
struct osmo_sccp_addr addr;
+ struct osmo_fsm_inst *fi;
};

struct msc *msc_alloc(struct osmo_sccp_addr *addr);
@@ -31,4 +33,7 @@

struct msc *msc_get(void);

+void msc_tx_reset(struct msc *msc);
+void msc_rx_reset_ack(struct msc *msc);
+
void msc_free(struct msc *msc);
diff --git a/src/osmo-bsc-nat/Makefile.am b/src/osmo-bsc-nat/Makefile.am
index 1dd82fd..8fd5667 100644
--- a/src/osmo-bsc-nat/Makefile.am
+++ b/src/osmo-bsc-nat/Makefile.am
@@ -32,6 +32,7 @@
logging.c \
main.c \
msc.c \
+ msc_fsm.c \
vty.c \
$(NULL)

diff --git a/src/osmo-bsc-nat/bsc_nat_fsm.c b/src/osmo-bsc-nat/bsc_nat_fsm.c
index 4193ae9..1d92ba3 100644
--- a/src/osmo-bsc-nat/bsc_nat_fsm.c
+++ b/src/osmo-bsc-nat/bsc_nat_fsm.c
@@ -286,24 +286,6 @@
case OSMO_PRIM(OSMO_SCU_PRIM_N_UNITDATA, PRIM_OP_INDICATION):
/* connection-less data received */
rc = bssap_handle_udt(sccp_inst, &prim->u.unitdata.calling_addr, oph->msg, msgb_l2len(oph->msg));
-
- /* FIXME: don't forward this to the MSC anymore, as soon as the
- * BSCNAT is able to do the RESET to MSC by itself. */
- addr = &prim->u.unitdata.calling_addr;
-
- if (sccp_sap_get_peer_addr_out(sccp_inst, addr, &peer_addr_out) < 0)
- goto error;
-
- LOGP(DMAIN, LOGL_DEBUG, "Fwd to %s\n", bsc_nat_print_addr_cn(&peer_addr_out));
-
- /* oph->msg stores oph and unitdata msg. Move oph->msg->data to
- * unitdata msg and send it again. */
- msgb_pull_to_l2(oph->msg);
- osmo_sccp_tx_unitdata(g_bsc_nat->cn.sccp_inst->scu,
- &g_bsc_nat->cn.sccp_inst->addr,
- &peer_addr_out,
- oph->msg->data,
- msgb_length(oph->msg));
break;

default:
diff --git a/src/osmo-bsc-nat/bssap.c b/src/osmo-bsc-nat/bssap.c
index 83eec99..f88bb20 100644
--- a/src/osmo-bsc-nat/bssap.c
+++ b/src/osmo-bsc-nat/bssap.c
@@ -25,6 +25,50 @@
#include <osmocom/bsc_nat/bsc.h>
#include <osmocom/bsc_nat/bsc_nat.h>
#include <osmocom/bsc_nat/logging.h>
+#include <osmocom/bsc_nat/msc.h>
+
+int bssap_tx_reset(struct bsc_nat_sccp_inst *sccp_inst, struct osmo_sccp_addr *addr)
+{
+ enum bsc_nat_net net = sccp_inst == g_bsc_nat->cn.sccp_inst ? BSC_NAT_NET_CN : BSC_NAT_NET_RAN;
+
+ LOGP(DMAIN, LOGL_NOTICE, "Tx RESET to %s\n", bsc_nat_print_addr(net, addr));
+
+ struct msgb *msg = gsm0808_create_reset();
+
+ return osmo_sccp_tx_unitdata_msg(sccp_inst->scu, &sccp_inst->addr, addr, msg);
+}
+
+static int bssap_cn_handle_reset_ack(struct osmo_sccp_addr *addr, struct msgb *msg, unsigned int length)
+{
+ struct msc *msc = msc_get();
+
+ if (msc->addr.pc != addr->pc) {
+ LOGP(DMAIN, LOGL_ERROR, "Unexpected Rx RESET ACK in CN from %s, which is not %s\n",
+ osmo_ss7_pointcode_print(NULL, addr->pc), talloc_get_name(msc));
+ return -1;
+ }
+
+ LOGP(DMAIN, LOGL_NOTICE, "Rx RESET ACK from %s\n", talloc_get_name(msc));
+ msc_rx_reset_ack(msc);
+
+ return 0;
+}
+
+static int bssap_cn_rcvmsg_udt(struct osmo_sccp_addr *addr, struct msgb *msg, unsigned int length)
+{
+ int ret = 0;
+
+ switch (msg->l3h[0]) {
+ case BSS_MAP_MSG_RESET_ACKNOWLEDGE:
+ ret = bssap_cn_handle_reset_ack(addr, msg, length);
+ break;
+ default:
+ LOGP(DMAIN, LOGL_NOTICE, "Unimplemented BSSMAP UDT %s\n", gsm0808_bssap_name(msg->l3h[0]));
+ break;
+ }
+
+ return ret;
+}

static int bssap_ran_handle_reset(struct osmo_sccp_addr *addr, struct msgb *msg, unsigned int length)
{
@@ -69,7 +113,8 @@

LOGP(DMAIN, LOGL_NOTICE, "Rx UDT BSSMAP %s\n", gsm0808_bssap_name(msg->l3h[0]));

- /* NOTE: bssap_cn_rcvmsg_udt() will be added in a future patch */
+ if (sccp_inst == g_bsc_nat->cn.sccp_inst)
+ return bssap_cn_rcvmsg_udt(addr, msg, length);
return bssap_ran_rcvmsg_udt(addr, msg, length);
}

diff --git a/src/osmo-bsc-nat/msc.c b/src/osmo-bsc-nat/msc.c
index 70f9d76..e78a8e6 100644
--- a/src/osmo-bsc-nat/msc.c
+++ b/src/osmo-bsc-nat/msc.c
@@ -23,6 +23,8 @@
#include <osmocom/bsc_nat/bsc_nat.h>
#include <osmocom/bsc_nat/logging.h>

+extern struct osmo_fsm msc_fsm;
+
struct msc *msc_alloc(struct osmo_sccp_addr *addr)
{
struct msc *msc = talloc_zero(g_bsc_nat, struct msc);
@@ -37,6 +39,11 @@
INIT_LLIST_HEAD(&msc->list);
llist_add(&msc->list, &g_bsc_nat->cn.mscs);

+ msc->fi = osmo_fsm_inst_alloc(&msc_fsm, msc, msc, LOGL_INFO, NULL);
+ OSMO_ASSERT(msc->fi);
+
+ msc_tx_reset(msc);
+
return msc;
}

@@ -67,5 +74,6 @@
{
LOGP(DMAIN, LOGL_DEBUG, "Del %s\n", talloc_get_name(msc));
llist_del(&msc->list);
+ osmo_fsm_inst_free(msc->fi);
talloc_free(msc);
}
diff --git a/src/osmo-bsc-nat/msc_fsm.c b/src/osmo-bsc-nat/msc_fsm.c
new file mode 100644
index 0000000..d8b89c6
--- /dev/null
+++ b/src/osmo-bsc-nat/msc_fsm.c
@@ -0,0 +1,154 @@
+/* (C) 2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
+ * Author: Oliver Smith <osmith@sysmocom.de>
+ * 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/lienses/>.
+ *
+ */
+
+#include "config.h"
+#include <osmocom/core/fsm.h>
+#include <osmocom/sigtran/sccp_sap.h>
+#include <osmocom/bsc_nat/bsc_nat.h>
+#include <osmocom/bsc_nat/bssap.h>
+#include <osmocom/bsc_nat/logging.h>
+#include <osmocom/bsc_nat/msc.h>
+
+#define X(s) (1 << (s))
+
+enum msc_fsm_states {
+ MSC_FSM_ST_DISCONNECTED,
+ MSC_FSM_ST_CONNECTING,
+ MSC_FSM_ST_CONNECTED,
+};
+
+enum msc_fsm_events {
+ MSC_FSM_EV_TX_RESET,
+ MSC_FSM_EV_RX_RESET_ACK,
+ MSC_FSM_EV_DISCONNECT
+};
+
+static void st_connecting(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+ switch (event) {
+ case MSC_FSM_EV_RX_RESET_ACK:
+ osmo_fsm_inst_state_chg(fi, MSC_FSM_ST_CONNECTED, 0, 0);
+ break;
+ default:
+ OSMO_ASSERT(false);
+ }
+}
+
+static void st_disconnected_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_stat)
+{
+ osmo_fsm_inst_dispatch(fi, MSC_FSM_EV_TX_RESET, NULL);
+}
+
+static void st_disconnected(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+ struct msc *msc = fi->priv;
+
+ switch (event) {
+ case MSC_FSM_EV_TX_RESET:
+ LOGP(DMAIN, LOGL_DEBUG, "Tx RESET to %s\n", talloc_get_name(msc));
+
+ if (bssap_tx_reset(g_bsc_nat->cn.sccp_inst, &msc->addr) < 0) {
+ LOGP(DMAIN, LOGL_ERROR, "Could not send RESET to MSC (SCCP not up yet?)\n");
+ }
+
+ /* Retry in 3s if RESET ACK was not received from MSC */
+ osmo_fsm_inst_state_chg(fi, MSC_FSM_ST_CONNECTING, 3, 0);
+
+ break;
+ default:
+ OSMO_ASSERT(false);
+ }
+}
+
+int msc_fsm_timer_cb(struct osmo_fsm_inst *fi)
+{
+ switch (fi->state) {
+ case MSC_FSM_ST_CONNECTING:
+ osmo_fsm_inst_state_chg(fi, MSC_FSM_ST_DISCONNECTED, 0, 0);
+ break;
+ default:
+ OSMO_ASSERT(false);
+ }
+ return 0;
+}
+
+static struct osmo_fsm_state msc_fsm_states[] = {
+ [MSC_FSM_ST_DISCONNECTED] = {
+ .name = "DISCONNECTED",
+ .in_event_mask = 0
+ | X(MSC_FSM_EV_TX_RESET)
+ ,
+ .out_state_mask = 0
+ | X(MSC_FSM_ST_CONNECTING)
+ ,
+ .action = st_disconnected,
+ .onenter = st_disconnected_on_enter,
+ },
+ [MSC_FSM_ST_CONNECTING] = {
+ .name = "CONNECTING",
+ .in_event_mask = 0
+ | X(MSC_FSM_EV_RX_RESET_ACK)
+ ,
+ .out_state_mask = 0
+ | X(MSC_FSM_ST_CONNECTED)
+ | X(MSC_FSM_ST_DISCONNECTED)
+ ,
+ .action = st_connecting,
+ },
+ [MSC_FSM_ST_CONNECTED] = {
+ .name = "CONNECTED",
+ .in_event_mask = 0
+ | X(MSC_FSM_EV_DISCONNECT)
+ ,
+ .out_state_mask = 0
+ | X(MSC_FSM_ST_DISCONNECTED)
+ ,
+ },
+};
+
+const struct value_string msc_fsm_event_names[] = {
+ OSMO_VALUE_STRING(MSC_FSM_EV_TX_RESET),
+ OSMO_VALUE_STRING(MSC_FSM_EV_RX_RESET_ACK),
+ OSMO_VALUE_STRING(MSC_FSM_EV_DISCONNECT),
+ { 0, NULL }
+};
+
+struct osmo_fsm msc_fsm = {
+ .name = "MSC",
+ .states = msc_fsm_states,
+ .num_states = ARRAY_SIZE(msc_fsm_states),
+ .log_subsys = DMAIN,
+ .event_names = msc_fsm_event_names,
+ .timer_cb = msc_fsm_timer_cb,
+};
+
+static __attribute__((constructor)) void msc_fsm_init(void)
+{
+ OSMO_ASSERT(osmo_fsm_register(&msc_fsm) == 0);
+}
+
+void msc_tx_reset(struct msc *msc)
+{
+ osmo_fsm_inst_dispatch(msc->fi, MSC_FSM_EV_TX_RESET, NULL);
+}
+
+void msc_rx_reset_ack(struct msc *msc)
+{
+ osmo_fsm_inst_dispatch(msc->fi, MSC_FSM_EV_RX_RESET_ACK, NULL);
+}

To view, visit change 27474. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: osmo-bsc-nat
Gerrit-Branch: master
Gerrit-Change-Id: Icfec3ec0168c7040e88a536fa48da339349fb6cf
Gerrit-Change-Number: 27474
Gerrit-PatchSet: 4
Gerrit-Owner: osmith <osmith@sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <laforge@osmocom.org>
Gerrit-Reviewer: osmith <osmith@sysmocom.de>
Gerrit-Reviewer: pespin <pespin@sysmocom.de>
Gerrit-MessageType: merged