neels has uploaded this change for review.
detect in/active CN links by RANAP RESET
Implement cnlink FSM. This is a copy of osmo-bsc/bssmap_reset.c, except
for the connection success/failure counting.
The reason to exclude the CONN_CFM_FAILURE/_SUCCESS: it is a rather
experimental feature and should probably rather be covered by PCSTATE
notifications and protocol layer timeout tuning (e.g. SCCP ia timers).
Related: SYS#6412
Change-Id: Id3eefdea889a736fd5957b80280fa45b9547b792
---
M include/osmocom/hnbgw/hnbgw.h
M include/osmocom/hnbgw/hnbgw_cn.h
M src/osmo-hnbgw/Makefile.am
A src/osmo-hnbgw/cnlink.c
M src/osmo-hnbgw/context_map.c
M src/osmo-hnbgw/hnbgw_cn.c
M src/osmo-hnbgw/hnbgw_vty.c
M src/osmo-hnbgw/tdefs.c
M tests/cnpool.vty
9 files changed, 420 insertions(+), 91 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-hnbgw refs/changes/75/33175/1
diff --git a/include/osmocom/hnbgw/hnbgw.h b/include/osmocom/hnbgw/hnbgw.h
index 3e1b6a4..69ce186 100644
--- a/include/osmocom/hnbgw/hnbgw.h
+++ b/include/osmocom/hnbgw/hnbgw.h
@@ -158,6 +158,8 @@
/* backpointer to CS or PS CN pool. */
struct hnbgw_cnpool *pool;
+ struct osmo_fsm_inst *fi;
+
int nr;
struct hnbgw_cnlink_cfg vty;
diff --git a/include/osmocom/hnbgw/hnbgw_cn.h b/include/osmocom/hnbgw/hnbgw_cn.h
index bd54a1f..04498d8 100644
--- a/include/osmocom/hnbgw/hnbgw_cn.h
+++ b/include/osmocom/hnbgw/hnbgw_cn.h
@@ -3,6 +3,7 @@
#include <osmocom/core/rate_ctr.h>
#include <osmocom/hnbgw/hnbgw.h>
+struct hnbgw_cnlink *cnlink_alloc(struct hnbgw_cnpool *cnpool, int nr);
struct hnbgw_cnlink *hnbgw_cnlink_find_by_addr(const struct hnbgw_sccp_user *hsu,
const struct osmo_sccp_addr *remote_addr);
struct hnbgw_cnlink *hnbgw_cnlink_select(struct hnbgw_context_map *map);
@@ -14,6 +15,12 @@
char *cnlink_sccp_addr_to_str(struct hnbgw_cnlink *cnlink, const struct osmo_sccp_addr *addr);
+bool cnlink_is_conn_ready(const struct hnbgw_cnlink *cnlink);
+void cnlink_rx_reset_cmd(struct hnbgw_cnlink *cnlink);
+void cnlink_rx_reset_ack(struct hnbgw_cnlink *cnlink);
+void cnlink_resend_reset(struct hnbgw_cnlink *cnlink);
+void cnlink_set_disconnected(struct hnbgw_cnlink *cnlink);
+
enum hnbgw_cnpool_ctr {
/* TODO: basic counters completely missing
* ...
diff --git a/src/osmo-hnbgw/Makefile.am b/src/osmo-hnbgw/Makefile.am
index 5fbdf74..910fdda 100644
--- a/src/osmo-hnbgw/Makefile.am
+++ b/src/osmo-hnbgw/Makefile.am
@@ -41,6 +41,7 @@
context_map_rua.c \
context_map_sccp.c \
hnbgw_cn.c \
+ cnlink.c \
ranap_rab_ass.c \
mgw_fsm.c \
tdefs.c \
diff --git a/src/osmo-hnbgw/cnlink.c b/src/osmo-hnbgw/cnlink.c
new file mode 100644
index 0000000..20b5cd9
--- /dev/null
+++ b/src/osmo-hnbgw/cnlink.c
@@ -0,0 +1,312 @@
+/* (C) 2023 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
+ * All Rights Reserved
+ *
+ * Author: Neels Hofmeyr
+ *
+ * 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 <osmocom/core/tdef.h>
+
+#include <osmocom/gsm/gsm23236.h>
+
+#include <osmocom/sigtran/sccp_helpers.h>
+
+#include <osmocom/ranap/ranap_ies_defs.h>
+#include <osmocom/ranap/ranap_msg_factory.h>
+
+#include <osmocom/hnbgw/hnbgw.h>
+#include <osmocom/hnbgw/hnbgw_cn.h>
+#include <osmocom/hnbgw/tdefs.h>
+#include <osmocom/hnbgw/context_map.h>
+
+static struct osmo_fsm cnlink_fsm;
+
+enum cnlink_fsm_state {
+ CNLINK_ST_DISC,
+ CNLINK_ST_CONN,
+};
+
+enum cnlink_fsm_event {
+ CNLINK_EV_RX_RESET,
+ CNLINK_EV_RX_RESET_ACK,
+};
+
+static const struct value_string cnlink_fsm_event_names[] = {
+ OSMO_VALUE_STRING(CNLINK_EV_RX_RESET),
+ OSMO_VALUE_STRING(CNLINK_EV_RX_RESET_ACK),
+ {}
+};
+
+static const struct osmo_tdef_state_timeout cnlink_timeouts[32] = {
+ [CNLINK_ST_DISC] = { .T = 4 },
+};
+
+#define cnlink_fsm_state_chg(FI, STATE) \
+ osmo_tdef_fsm_inst_state_chg(FI, STATE, \
+ cnlink_timeouts, \
+ hnbgw_T_defs, \
+ -1)
+
+struct hnbgw_cnlink *cnlink_alloc(struct hnbgw_cnpool *cnpool, int nr)
+{
+ struct osmo_fsm_inst *fi;
+ struct hnbgw_cnlink *cnlink;
+
+ char *name = talloc_asprintf(OTC_SELECT, "%s-%d", cnpool->peer_name, nr);
+
+ fi = osmo_fsm_inst_alloc(&cnlink_fsm, g_hnbgw, NULL, LOGL_DEBUG, name);
+ OSMO_ASSERT(fi);
+ cnlink = talloc_zero(g_hnbgw, struct hnbgw_cnlink);
+ fi->priv = cnlink;
+
+ *cnlink = (struct hnbgw_cnlink){
+ .name = name,
+ .pool = cnpool,
+ .fi = fi,
+ .nr = nr,
+ .vty = {
+ /* VTY config defaults for the new cnlink */
+ .nri_ranges = osmo_nri_ranges_alloc(cnlink),
+ },
+ .allow_attach = true,
+ .ctrs = rate_ctr_group_alloc(g_hnbgw, cnpool->cnlink_ctrg_desc, nr),
+ };
+ talloc_steal(cnlink, name);
+ INIT_LLIST_HEAD(&cnlink->map_list);
+
+ llist_add_tail(&cnlink->entry, &cnpool->cnlinks);
+ LOG_CNLINK(cnlink, DCN, LOGL_DEBUG, "allocated\n");
+
+ /* Immediately (1ms) kick off reset sending mechanism */
+ osmo_fsm_inst_state_chg_ms(fi, CNLINK_ST_DISC, 1, 0);
+ return cnlink;
+}
+
+void cnlink_term_and_free(struct hnbgw_cnlink *cnlink)
+{
+ if (!cnlink)
+ return;
+ osmo_fsm_inst_term(cnlink->fi, OSMO_FSM_TERM_REQUEST, NULL);
+ talloc_free(cnlink);
+}
+
+static void link_up(struct hnbgw_cnlink *cnlink)
+{
+ LOGPFSML(cnlink->fi, LOGL_NOTICE, "link up\n");
+}
+
+static void link_lost(struct hnbgw_cnlink *cnlink)
+{
+ struct hnbgw_context_map *map, *map2;
+
+ LOGPFSML(cnlink->fi, LOGL_NOTICE, "link lost\n");
+
+ llist_for_each_entry_safe(map, map2, &cnlink->map_list, hnbgw_cnlink_entry)
+ context_map_cnlink_lost(map);
+}
+
+static void tx_reset(struct hnbgw_cnlink *cnlink)
+{
+ struct msgb *msg;
+ RANAP_Cause_t cause = {
+ .present = RANAP_Cause_PR_transmissionNetwork,
+ .choice. transmissionNetwork = RANAP_CauseTransmissionNetwork_signalling_transport_resource_failure,
+ };
+
+ if (!cnlink)
+ return;
+
+ if (!cnlink->hnbgw_sccp_user || !cnlink->use.remote_addr_name) {
+ LOG_CNLINK(cnlink, DRANAP, LOGL_DEBUG, "not yet configured, not sending RANAP RESET\n");
+ return;
+ }
+
+ LOG_CNLINK(cnlink, DRANAP, LOGL_DEBUG, "Tx RANAP RESET to %s %s\n",
+ cnlink_is_cs(cnlink) ? "IuCS" : "IuPS",
+ cnlink_sccp_addr_to_str(cnlink, &cnlink->remote_addr));
+
+ msg = ranap_new_msg_reset(cnlink->pool->domain, &cause);
+
+ osmo_sccp_tx_unitdata_msg(cnlink->hnbgw_sccp_user->sccp_user,
+ &cnlink->hnbgw_sccp_user->local_addr,
+ &cnlink->remote_addr,
+ msg);
+}
+
+static void tx_reset_ack(struct hnbgw_cnlink *cnlink)
+{
+ struct msgb *msg;
+ struct osmo_sccp_instance *sccp = cnlink_sccp(cnlink);
+
+ if (!sccp) {
+ LOG_CNLINK(cnlink, DRANAP, LOGL_ERROR, "cannot send RANAP RESET ACK: no CN link\n");
+ return;
+ }
+
+ LOG_CNLINK(cnlink, DRANAP, LOGL_NOTICE, "Tx RANAP RESET ACK %s %s --> %s\n",
+ cnlink_is_cs(cnlink) ? "IuCS" : "IuPS",
+ cnlink_sccp_addr_to_str(cnlink, &cnlink->hnbgw_sccp_user->local_addr),
+ cnlink_sccp_addr_to_str(cnlink, &cnlink->remote_addr));
+
+ msg = ranap_new_msg_reset_ack(cnlink->pool->domain, NULL);
+
+ osmo_sccp_tx_unitdata_msg(cnlink->hnbgw_sccp_user->sccp_user,
+ &cnlink->hnbgw_sccp_user->local_addr,
+ &cnlink->remote_addr,
+ msg);
+}
+
+static void cnlink_disc_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)
+{
+ struct hnbgw_cnlink *cnlink = (struct hnbgw_cnlink*)fi->priv;
+ if (prev_state == CNLINK_ST_CONN)
+ link_lost(cnlink);
+}
+
+static void cnlink_disc_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+ struct hnbgw_cnlink *cnlink = (struct hnbgw_cnlink*)fi->priv;
+ switch (event) {
+
+ case CNLINK_EV_RX_RESET:
+ tx_reset_ack(cnlink);
+ cnlink_fsm_state_chg(fi, CNLINK_ST_CONN);
+ break;
+
+ case CNLINK_EV_RX_RESET_ACK:
+ cnlink_fsm_state_chg(fi, CNLINK_ST_CONN);
+ break;
+
+ default:
+ OSMO_ASSERT(false);
+ }
+}
+
+static void cnlink_conn_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)
+{
+ struct hnbgw_cnlink *cnlink = (struct hnbgw_cnlink*)fi->priv;
+ if (prev_state != CNLINK_ST_CONN)
+ link_up(cnlink);
+}
+
+static void cnlink_conn_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+ struct hnbgw_cnlink *cnlink = (struct hnbgw_cnlink*)fi->priv;
+
+ switch (event) {
+
+ case CNLINK_EV_RX_RESET:
+ /* We were connected, but the remote side has restarted. */
+ link_lost(cnlink);
+ tx_reset_ack(cnlink);
+ link_up(cnlink);
+ break;
+
+ case CNLINK_EV_RX_RESET_ACK:
+ LOGPFSML(fi, LOGL_INFO, "Link is already up, ignoring RESET ACK\n");
+ break;
+
+ default:
+ OSMO_ASSERT(false);
+ }
+}
+
+static int cnlink_fsm_timer_cb(struct osmo_fsm_inst *fi)
+{
+ struct hnbgw_cnlink *cnlink = (struct hnbgw_cnlink*)fi->priv;
+
+ tx_reset(cnlink);
+
+ /* (re-)enter disconnect state to resend RESET after timeout. */
+ cnlink_fsm_state_chg(fi, CNLINK_ST_DISC);
+
+ /* Return 0 to not terminate the fsm */
+ return 0;
+}
+
+#define S(x) (1 << (x))
+
+static struct osmo_fsm_state cnlink_fsm_states[] = {
+ [CNLINK_ST_DISC] = {
+ .name = "DISC",
+ .in_event_mask = 0
+ | S(CNLINK_EV_RX_RESET)
+ | S(CNLINK_EV_RX_RESET_ACK)
+ ,
+ .out_state_mask = 0
+ | S(CNLINK_ST_DISC)
+ | S(CNLINK_ST_CONN)
+ ,
+ .onenter = cnlink_disc_onenter,
+ .action = cnlink_disc_action,
+ },
+ [CNLINK_ST_CONN] = {
+ .name = "CONN",
+ .in_event_mask = 0
+ | S(CNLINK_EV_RX_RESET)
+ | S(CNLINK_EV_RX_RESET_ACK)
+ ,
+ .out_state_mask = 0
+ | S(CNLINK_ST_DISC)
+ | S(CNLINK_ST_CONN)
+ ,
+ .onenter = cnlink_conn_onenter,
+ .action = cnlink_conn_action,
+ },
+};
+
+static struct osmo_fsm cnlink_fsm = {
+ .name = "cnlink",
+ .states = cnlink_fsm_states,
+ .num_states = ARRAY_SIZE(cnlink_fsm_states),
+ .log_subsys = DRANAP,
+ .timer_cb = cnlink_fsm_timer_cb,
+ .event_names = cnlink_fsm_event_names,
+};
+
+bool cnlink_is_conn_ready(const struct hnbgw_cnlink *cnlink)
+{
+ return cnlink->fi->state == CNLINK_ST_CONN;
+}
+
+void cnlink_resend_reset(struct hnbgw_cnlink *cnlink)
+{
+ /* Immediately (1ms) kick off reset sending mechanism */
+ osmo_fsm_inst_state_chg_ms(cnlink->fi, CNLINK_ST_DISC, 1, 0);
+}
+
+void cnlink_set_disconnected(struct hnbgw_cnlink *cnlink)
+{
+ /* Go to disconnected state, with the normal RESET timeout to re-send RESET. */
+ cnlink_fsm_state_chg(cnlink->fi, CNLINK_ST_DISC);
+}
+
+static __attribute__((constructor)) void cnlink_fsm_init(void)
+{
+ OSMO_ASSERT(osmo_fsm_register(&cnlink_fsm) == 0);
+}
+
+void cnlink_rx_reset_cmd(struct hnbgw_cnlink *cnlink)
+{
+ osmo_fsm_inst_dispatch(cnlink->fi, CNLINK_EV_RX_RESET, NULL);
+}
+
+void cnlink_rx_reset_ack(struct hnbgw_cnlink *cnlink)
+{
+ osmo_fsm_inst_dispatch(cnlink->fi, CNLINK_EV_RX_RESET_ACK, NULL);
+}
+
diff --git a/src/osmo-hnbgw/context_map.c b/src/osmo-hnbgw/context_map.c
index 73a7ecc..67a0d82 100644
--- a/src/osmo-hnbgw/context_map.c
+++ b/src/osmo-hnbgw/context_map.c
@@ -133,6 +133,7 @@
cnlink_selected->use.remote_addr_name ? " ": "",
cnlink_selected->use.remote_addr_name ? : "",
hsu->name,
+ /* printing the entire SCCP address is quite long, rather just print the point-code */
osmo_ss7_pointcode_print(hsu->ss7, hsu->local_addr.pc),
osmo_ss7_pointcode_print2(hsu->ss7, cnlink_selected->remote_addr.pc)
);
diff --git a/src/osmo-hnbgw/hnbgw_cn.c b/src/osmo-hnbgw/hnbgw_cn.c
index d577fb4..3ae373d 100644
--- a/src/osmo-hnbgw/hnbgw_cn.c
+++ b/src/osmo-hnbgw/hnbgw_cn.c
@@ -41,60 +41,6 @@
#include <osmocom/ranap/ranap_msg_factory.h>
#include <osmocom/hnbgw/context_map.h>
-#if 0
-this code will soon move to new file cnlink.c
-static int transmit_rst(struct hnbgw_cnlink *cnlink)
-{
- struct msgb *msg;
- RANAP_Cause_t cause = {
- .present = RANAP_Cause_PR_transmissionNetwork,
- .choice. transmissionNetwork = RANAP_CauseTransmissionNetwork_signalling_transport_resource_failure,
- };
-
- if (!cnlink)
- return -1;
-
- if (!cnlink->hnbgw_sccp_user) {
- LOG_CNLINK(cnlink, DRANAP, LOGL_ERROR, "cannot send RANAP RESET: no CN link\n");
- return -1;
- }
-
- LOG_CNLINK(cnlink, DRANAP, LOGL_NOTICE, "Tx RANAP RESET to %s %s\n",
- cnlink_is_cs(cnlink) ? "IuCS" : "IuPS",
- osmo_sccp_inst_addr_name(cnlink->hnbgw_sccp_user->sccp, &cnlink->remote_addr));
-
- msg = ranap_new_msg_reset(cnlink->pool->domain, &cause);
-
- return osmo_sccp_tx_unitdata_msg(cnlink->hnbgw_sccp_user->sccp_user,
- &cnlink->local_addr,
- &cnlink->remote_addr,
- msg);
-}
-#endif
-
-static int transmit_reset_ack(struct hnbgw_cnlink *cnlink)
-{
- struct msgb *msg;
- struct osmo_sccp_instance *sccp = cnlink_sccp(cnlink);
-
- if (!sccp) {
- LOG_CNLINK(cnlink, DRANAP, LOGL_ERROR, "cannot send RANAP RESET ACK: no CN link\n");
- return -1;
- }
-
- LOG_CNLINK(cnlink, DRANAP, LOGL_NOTICE, "Tx RANAP RESET ACK %s %s --> %s\n",
- cnlink_is_cs(cnlink) ? "IuCS" : "IuPS",
- cnlink_sccp_addr_to_str(cnlink, &cnlink->hnbgw_sccp_user->local_addr),
- cnlink_sccp_addr_to_str(cnlink, &cnlink->remote_addr));
-
- msg = ranap_new_msg_reset_ack(cnlink->pool->domain, NULL);
-
- return osmo_sccp_tx_unitdata_msg(cnlink->hnbgw_sccp_user->sccp_user,
- &cnlink->hnbgw_sccp_user->local_addr,
- &cnlink->remote_addr,
- msg);
-}
-
/***********************************************************************
* Incoming primitives from SCCP User SAP
***********************************************************************/
@@ -111,33 +57,45 @@
domain = ies.cN_DomainIndicator;
ranap_free_reseties(&ies);
- LOG_CNLINK(cnlink, DRANAP, LOGL_NOTICE, "Rx RESET from %s %s, returning ACK\n",
- domain == DOMAIN_CS ? "IuCS" : "IuPS",
- osmo_sccp_inst_addr_name(cnlink_sccp(cnlink), &unitdata->calling_addr));
+ if (rc) {
+ LOG_CNLINK(cnlink, DCN, LOGL_ERROR, "Rx RESET: cannot decode IEs\n");
+ return -1;
+ }
- /* FIXME: actually reset connections, if any */
+ if (cnlink->pool->domain != domain) {
+ LOG_CNLINK(cnlink, DCN, LOGL_ERROR, "Rx RESET indicates domain %s, but this is %s on domain %s\n",
+ ranap_domain_name(domain), cnlink->name, ranap_domain_name(cnlink->pool->domain));
+ return -1;
+ }
- if (transmit_reset_ack(cnlink))
- LOGP(DRANAP, LOGL_ERROR, "Error: cannot send RESET ACK to %s %s\n",
- domain == DOMAIN_CS ? "IuCS" : "IuPS",
- osmo_sccp_inst_addr_name(cnlink_sccp(cnlink), &unitdata->calling_addr));
-
- return rc;
+ cnlink_rx_reset_cmd(cnlink);
+ return 0;
}
static int cn_ranap_rx_reset_ack(struct hnbgw_cnlink *cnlink,
RANAP_SuccessfulOutcome_t *omsg)
{
+ RANAP_CN_DomainIndicator_t domain;
RANAP_ResetAcknowledgeIEs_t ies;
int rc;
rc = ranap_decode_resetacknowledgeies(&ies, &omsg->value);
-
- /* FUTURE: will do something useful in commit 'detect in/active CN links by RANAP RESET'
- * Id3eefdea889a736fd5957b80280fa45b9547b792 */
-
+ domain = ies.cN_DomainIndicator;
ranap_free_resetacknowledgeies(&ies);
- return rc;
+
+ if (rc) {
+ LOG_CNLINK(cnlink, DCN, LOGL_ERROR, "Rx RESET ACK: cannot decode IEs\n");
+ return -1;
+ }
+
+ if (cnlink->pool->domain != domain) {
+ LOG_CNLINK(cnlink, DCN, LOGL_ERROR, "Rx RESET ACK indicates domain %s, but this is %s on domain %s\n",
+ ranap_domain_name(domain), cnlink->name, ranap_domain_name(cnlink->pool->domain));
+ return -1;
+ }
+
+ cnlink_rx_reset_ack(cnlink);
+ return 0;
}
static int cn_ranap_rx_paging_cmd(struct hnbgw_cnlink *cnlink,
@@ -654,28 +612,6 @@
hnbgw_cnpool_cnlinks_start_or_restart(cnpool);
}
-static struct hnbgw_cnlink *cnlink_alloc(struct hnbgw_cnpool *cnpool, int nr)
-{
- struct hnbgw_cnlink *cnlink;
- cnlink = talloc_zero(g_hnbgw, struct hnbgw_cnlink);
- *cnlink = (struct hnbgw_cnlink){
- .name = talloc_asprintf(cnlink, "%s-%d", cnpool->peer_name, nr),
- .pool = cnpool,
- .nr = nr,
- .vty = {
- /* VTY config defaults for the new cnlink */
- .nri_ranges = osmo_nri_ranges_alloc(cnlink),
- },
- .allow_attach = true,
- .ctrs = rate_ctr_group_alloc(g_hnbgw, cnpool->cnlink_ctrg_desc, nr),
- };
- INIT_LLIST_HEAD(&cnlink->map_list);
-
- llist_add_tail(&cnlink->entry, &cnpool->cnlinks);
- LOG_CNLINK(cnlink, DCN, LOGL_DEBUG, "allocated\n");
- return cnlink;
-}
-
struct hnbgw_cnlink *cnlink_get_nr(struct hnbgw_cnpool *cnpool, int nr, bool create_if_missing)
{
struct hnbgw_cnlink *cnlink;
diff --git a/src/osmo-hnbgw/hnbgw_vty.c b/src/osmo-hnbgw/hnbgw_vty.c
index 462a4fc..bee34f1 100644
--- a/src/osmo-hnbgw/hnbgw_vty.c
+++ b/src/osmo-hnbgw/hnbgw_vty.c
@@ -710,6 +710,35 @@
return CMD_SUCCESS;
}
+DEFUN(cnlink_ranap_reset, cnlink_ranap_reset_cmd,
+ "(msc|sgsn) " CNLINK_NR_RANGE " ranap reset",
+ "Manipulate an IuCS link to an MSC\n"
+ "Manipulate an IuPS link to an SGSN\n"
+ "MSC/SGSN nr\n"
+ "Manipulate RANAP layer of Iu-interface\n"
+ "Flip this CN link to disconnected state and re-send RANAP RESET\n")
+{
+ struct hnbgw_cnpool *cnpool;
+ struct hnbgw_cnlink *cnlink;
+ const char *msc_sgsn = argv[0];
+ int nr = atoi(argv[1]);
+
+ if (!strcmp("msc", msc_sgsn))
+ cnpool = &g_hnbgw->sccp.cnpool_iucs;
+ else
+ cnpool = &g_hnbgw->sccp.cnpool_iups;
+
+ cnlink = cnlink_get_nr(cnpool, nr, false);
+ if (!cnlink) {
+ vty_out(vty, "%% No such %s: nr %d\n", msc_sgsn, nr);
+ return CMD_WARNING;
+ }
+
+ LOG_CNLINK(cnlink, DCN, LOGL_NOTICE, "VTY requests BSSMAP RESET\n");
+ cnlink_resend_reset(cnlink);
+ return CMD_SUCCESS;
+}
+
#define APPLY_STR "Immediately use configuration modified via telnet VTY, and restart components as needed.\n"
#define SCCP_RESTART_STR \
" If 'remote-addr' changed, related SCCP links will be restarted, possibly dropping active UE contexts."
@@ -976,4 +1005,5 @@
install_element_ve(&show_nri_cmd);
install_element(ENABLE_NODE, &cnpool_roundrobin_next_cmd);
+ install_element(ENABLE_NODE, &cnlink_ranap_reset_cmd);
}
diff --git a/src/osmo-hnbgw/tdefs.c b/src/osmo-hnbgw/tdefs.c
index 645cdbf..992c140 100644
--- a/src/osmo-hnbgw/tdefs.c
+++ b/src/osmo-hnbgw/tdefs.c
@@ -32,6 +32,7 @@
};
struct osmo_tdef hnbgw_T_defs[] = {
+ {.T = 4, .default_val = 5, .desc = "Timeout to receive RANAP RESET ACKNOWLEDGE from an MSC/SGSN" },
{.T = -31, .default_val = 5, .desc = "Timeout for discarding a partially released context map (RUA <-> SCCP)" },
{.T = -1002, .default_val = 10, .desc = "Timeout for the HNB to respond to PS RAB Assignment Request" },
{ }
diff --git a/tests/cnpool.vty b/tests/cnpool.vty
index 9745306..2de56a7 100644
--- a/tests/cnpool.vty
+++ b/tests/cnpool.vty
@@ -1,4 +1,26 @@
OsmoHNBGW> enable
+OsmoHNBGW# list
+...
+ (msc|sgsn) <0-1000> ranap reset
+...
+OsmoHNBGW# msc?
+ msc Manipulate an IuCS link to an MSC
+OsmoHNBGW# msc ?
+ <0-1000> MSC/SGSN nr
+OsmoHNBGW# msc 0 ?
+ ranap Manipulate RANAP layer of Iu-interface
+OsmoHNBGW# msc 0 ranap ?
+ reset Flip this CN link to disconnected state and re-send RANAP RESET
+
+OsmoHNBGW# sgsn?
+ sgsn Manipulate an IuPS link to an SGSN
+OsmoHNBGW# sgsn ?
+ <0-1000> MSC/SGSN nr
+OsmoHNBGW# sgsn 0 ?
+ ranap Manipulate RANAP layer of Iu-interface
+OsmoHNBGW# sgsn 0 ranap ?
+ reset Flip this CN link to disconnected state and re-send RANAP RESET
+
OsmoHNBGW# configure terminal
OsmoHNBGW(config)# ### cnpool doc strings
To view, visit change 33175. To unsubscribe, or for help writing mail filters, visit settings.