diff options
authorPhilipp Maier <pmaier@sysmocom.de>2018-02-22 16:44:41 +0100
committerPhilipp Maier <pmaier@sysmocom.de>2018-03-07 18:10:23 +0100
commitce1298b7dce06a6577da1df328f901d6f8a12501 (patch)
parent48d4ec06e180cfb60556ce6c565620078bbea8db (diff)
a_iface: fix BSSMAP reset handling
When osmo-msc restarts it looses all information about the BSC. The BSC will not be aware of the reboot and on the next communication attemt it will notice that something is wrong and start the reset procedure on his side. osmo-msc will receive the reset messages and send a reset. The reset is received. Osmo-msc detects that no context information is created yet. The context is created. Then it is checked if the UNITTDATA message that came in is a reset. If it is one. Nothing happens. The UNITTDATA is passed on and triggers the RESET-ACK some layers above. Unfortunately by the current code this also means that no reset FSM is created and therefore a_reset_conn_ready() can never be true. Which means it will also drop any legitimate reset from the BSC in the future. - Ensure that the reset FSM is always created when a new BSC context is created - Make sure that reset related traffic always passes so that the higher layers can handle the procedure properly Change-Id: I3fdcec5dbeaa0e21fd6a92568a623faa368239be
1 files changed, 17 insertions, 15 deletions
diff --git a/src/libmsc/a_iface.c b/src/libmsc/a_iface.c
index 86c2e04b6..79b1b4c8a 100644
--- a/src/libmsc/a_iface.c
+++ b/src/libmsc/a_iface.c
@@ -478,7 +478,7 @@ void a_start_reset(struct bsc_context *bsc_ctx, bool already_connected)
bsc_ctx->reset = a_reset_alloc(bsc_ctx, bsc_name, a_reset_cb, bsc_ctx, already_connected);
-/* determine if given msg is a BSSMAP RESET (true) or not (false) */
+/* determine if given msg is BSSMAP RESET related (true) or not (false) */
static bool bssmap_is_reset(struct msgb *msg)
struct bssmap_header *bs = (struct bssmap_header *)msgb_l2(msg);
@@ -492,6 +492,9 @@ static bool bssmap_is_reset(struct msgb *msg)
if (msg->l2h[sizeof(*bs)] == BSS_MAP_MSG_RESET)
return true;
+ if (msg->l2h[sizeof(*bs)] == BSS_MAP_MSG_RESET_ACKNOWLEDGE)
+ return true;
return false;
@@ -555,26 +558,25 @@ static int sccp_sap_up(struct osmo_prim_hdr *oph, void *_scu)
/* Handle inbound UNITDATA */
+ /* Get BSC context, create a new one if necessary */
a_conn_info.bsc = get_bsc_context_by_sccp_addr(&scu_prim->u.unitdata.calling_addr);
if (!a_conn_info.bsc) {
/* We haven't heard from this BSC before, allocate it */
a_conn_info.bsc = add_bsc(&scu_prim->u.unitdata.called_addr,
&scu_prim->u.unitdata.calling_addr, scu);
- /* if this not an inbound RESET, trigger an outbound RESET */
- if (!bssmap_is_reset(oph->msg)) {
- LOGP(DBSSAP, LOGL_NOTICE, "Ignoring N-UNITDATA.ind(%s), BSC not reset yet\n",
- msgb_hexdump_l2(oph->msg));
- a_start_reset(a_conn_info.bsc, false);
- break;
- }
- } else {
- /* This BSC is already known to us, check if we have been through reset yet */
- if (a_reset_conn_ready(a_conn_info.bsc->reset) == false) {
- LOGP(DBSSAP, LOGL_NOTICE, "Ignoring N-UNITDATA.ind(%s), BSC not reset yet\n",
- msgb_hexdump_l2(oph->msg));
- break;
- }
+ /* Make sure that reset procedure is started */
+ a_start_reset(a_conn_info.bsc, false);
+ /* As long as we are in the reset phase, only reset related BSSMAP messages may pass
+ * beond here. */
+ if (!bssmap_is_reset(oph->msg) && a_reset_conn_ready(a_conn_info.bsc->reset) == false) {
+ LOGP(DBSSAP, LOGL_NOTICE, "Ignoring N-UNITDATA.ind(%s), BSC not reset yet\n",
+ msgb_hexdump_l2(oph->msg));
+ break;
+ }
DEBUGP(DBSSAP, "N-UNITDATA.ind(%s)\n", msgb_hexdump_l2(oph->msg));
a_sccp_rx_udt(scu, &a_conn_info, oph->msg);