laforge submitted this change.

View Change

Approvals: laforge: Looks good to me, approved fixeria: Looks good to me, but someone else must approve Jenkins Builder: Verified
Implement ITU Q.704 T10 timer

Implement timer T10 used for periodic ASP Audit procedure as described
in:
* ITU Q.704 13.5.2
* rfc4666 4.5.3
* ETSI TS 102 142 V1.1.1

This procedure is used in order to recover the signalling route
availability information that may not have been received because of
some signalling network failure.

Related: OS#6883
Change-Id: Ic12b1aa8f2a02f32615dade34f0e1f01b2535f7b
---
M src/ss7_instance.c
M src/ss7_instance.h
M src/ss7_route.c
M src/ss7_route.h
M tests/vty/osmo_stp_test.vty
M tests/vty/ss7_asp_test.vty
6 files changed, 94 insertions(+), 3 deletions(-)

diff --git a/src/ss7_instance.c b/src/ss7_instance.c
index 1c5e113..4aadc65 100644
--- a/src/ss7_instance.c
+++ b/src/ss7_instance.c
@@ -67,12 +67,16 @@
{ .T = SS7_INST_XUA_T8, .default_val = SS7_INST_XUA_DEFAULT_T8_MSEC, .unit = OSMO_TDEF_MS,
.desc = "T8 - Transfer prohibited inhibition timer (transient solution) (ms)",
.min_val = 800, .max_val = 1200},
+ { .T = SS7_INST_XUA_T10, .default_val = SS7_INST_XUA_DEFAULT_T10_SEC, .unit = OSMO_TDEF_S,
+ .desc = "T10 - Waiting to repeat signalling route set test message (s)",
+ .min_val = 30, .max_val = 60},
{}
};

/* ITU Q.704 16.8 Timers and timer values */
const struct value_string ss7_instance_xua_timer_names[] = {
{ SS7_INST_XUA_T8, "T8" },
+ { SS7_INST_XUA_T10, "T10" },
{}
};

diff --git a/src/ss7_instance.h b/src/ss7_instance.h
index 29310f4..6861d40 100644
--- a/src/ss7_instance.h
+++ b/src/ss7_instance.h
@@ -22,6 +22,7 @@
enum ss7_instance_xua_timer {
/* 0 kept unused on purpose since it's handled specially by osmo_fsm */
SS7_INST_XUA_T8 = 1, /* Q.704 T8 */
+ SS7_INST_XUA_T10, /* Q.704 T10 */
/* This must remain the last item: */
SS7_INST_XUA_TIMERS_LEN
};
@@ -29,6 +30,7 @@
extern const struct osmo_tdef ss7_instance_xua_timer_defaults[SS7_INST_XUA_TIMERS_LEN];
/* According to SUA RFC3868 Section 8, M3UA RFC4666 Section 4.3.4.1 */
#define SS7_INST_XUA_DEFAULT_T8_MSEC 1000
+#define SS7_INST_XUA_DEFAULT_T10_SEC 45

enum ss7_instance_ctr {
SS7_INST_CTR_PKT_RX_TOTAL,
diff --git a/src/ss7_route.c b/src/ss7_route.c
index 7d22144..ce60bc1 100644
--- a/src/ss7_route.c
+++ b/src/ss7_route.c
@@ -33,6 +33,8 @@
#include "ss7_route.h"
#include "ss7_route_table.h"
#include "ss7_internal.h"
+#include "xua_internal.h"
+#include "ss7_vty.h"

/***********************************************************************
* SS7 Routes
@@ -46,6 +48,57 @@
{}
};

+/* Figure 46/Q.704 (sheet 1 of 3) RSRT: "Start T10" */
+static void t10_audit_timer_start(struct osmo_ss7_route *rt)
+{
+ unsigned int t10_sec = osmo_tdef_get(rt->rtable->inst->cfg.T_defs_xua, SS7_INST_XUA_T10, OSMO_TDEF_S, -1);
+ LOGPRT(rt, DLSS7, LOGL_INFO, "Start T10 (%us)\n", t10_sec);
+ osmo_timer_schedule(&rt->t10_audit_timer, t10_sec, 0);
+}
+
+/* Figure 46/Q.704 (sheet 1 of 3) RSRT: "Stop T10" */
+static void t10_audit_timer_stop(struct osmo_ss7_route *rt)
+{
+ LOGPRT(rt, DLSS7, LOGL_INFO, "Stop T10\n");
+ osmo_timer_del(&rt->t10_audit_timer);
+}
+
+/* Figure 46/Q.704 (sheet 1 of 3) RSRT: "T10" */
+static void t10_audit_timer_cb(void *_rt)
+{
+ struct osmo_ss7_route *rt = _rt;
+
+ LOGPRT(rt, DLSS7, LOGL_INFO, "T10 timeout\n");
+
+ /* "Signalling route set test RSRT → HMRT" */
+ if (rt->dest.as) {
+ struct osmo_ss7_as *as = rt->dest.as;
+ uint32_t rctx = htonl(as->cfg.routing_key.context);
+ uint32_t aff_pc = htonl(rt->cfg.pc); /* mask = 0 */
+ char buf_pc[MAX_PC_STR_LEN];
+ struct ss7_as_asp_assoc *assoc;
+
+ llist_for_each_entry(assoc, &as->assoc_asp_list, as_entry) {
+ struct osmo_ss7_asp *asp = assoc->asp;
+
+ /* SSNM is only permitted for ASPs in ACTIVE state (RFC4666 4.3.1) */
+ if (!osmo_ss7_asp_active(asp))
+ continue;
+
+ LOGPASP(asp, DLSS7, LOGL_INFO, "T10: Tx DAUD pc=%u=%s rtcx=%u\n",
+ rt->cfg.pc,
+ osmo_ss7_pointcode_print_buf(buf_pc, sizeof(buf_pc), asp->inst, rt->cfg.pc),
+ rctx);
+ xua_tx_snm_daud(asp, &rctx, 1, &aff_pc, 1, "T10");
+ }
+ } else if (rt->dest.linkset) {
+ LOGPRT(rt, DLSS7, LOGL_INFO, "T10 on linkset route not implemented!\n");
+ return; /* no need to keep printing "not implemented" repeteadly... */
+ }
+
+ t10_audit_timer_start(rt);
+}
+
/*! \brief Allocate a route entry
* \param[in] rtbl Routing Table where the route belongs
* \param[in] pc Point Code of the destination of the route
@@ -94,6 +147,9 @@
rt->cfg.pc = osmo_ss7_pc_normalize(&rtbl->inst->cfg.pc_fmt, pc);
rt->cfg.priority = OSMO_SS7_ROUTE_PRIO_DEFAULT;
rt->cfg.dyn_allocated = dynamic;
+
+ osmo_timer_setup(&rt->t10_audit_timer, t10_audit_timer_cb, rt);
+
return rt;
}

@@ -240,6 +296,8 @@
"Destroying route: %s\n", osmo_ss7_route_name(rt, false));
ss7_combined_linkset_del_route(rt);
}
+
+ osmo_timer_del(&rt->t10_audit_timer);
talloc_free(rt);
}

@@ -404,6 +462,31 @@

void ss7_route_update_route_status(struct osmo_ss7_route *rt, enum osmo_ss7_route_status status)
{
- LOGPRT(rt, DLSS7, LOGL_NOTICE, "changed to status '%s'\n", ss7_route_status_name(status));
+ LOGPRT(rt, DLSS7, rt->status != status ? LOGL_NOTICE : LOGL_DEBUG,
+ "changed to status '%s'\n", ss7_route_status_name(status));
+
+ /* "Signalling route set test RSRT → HMRT" */
+ if (rt->dest.as) {
+ int role = ss7_as_get_local_role(rt->dest.as);
+ if (role == OSMO_SS7_ASP_ROLE_ASP ||
+ role == OSMO_SS7_ASP_ROLE_IPSP) {
+ /* Figure 46/Q.704 (sheet 1 of 3) - Signalling route management; signalling route set test control (RSRT) */
+ if (rt->status == OSMO_SS7_ROUTE_STATUS_AVAILABLE &&
+ status != OSMO_SS7_ROUTE_STATUS_AVAILABLE) {
+ /* rt becomes restricted or unavailable:
+ * "Transfer prohibited received", "Start route set test RTPC → RSRT" -> "Start T10". */
+ unsigned int t10_sec = osmo_tdef_get(rt->rtable->inst->cfg.T_defs_xua, SS7_INST_XUA_T10, OSMO_TDEF_S, -1);
+ osmo_timer_schedule(&rt->t10_audit_timer, t10_sec, 0);
+ t10_audit_timer_start(rt);
+ } else if (rt->status != OSMO_SS7_ROUTE_STATUS_AVAILABLE &&
+ status == OSMO_SS7_ROUTE_STATUS_AVAILABLE) {
+ /* rt becomes available, "Signalling route available RTAC → RSRT" -> "Stop T10". */
+ t10_audit_timer_stop(rt);
+ }
+ }
+ } else if (rt->dest.linkset) {
+ LOGPRT(rt, DLSS7, LOGL_NOTICE, "update_route_status on linkset route not implemented!\n");
+ }
+
rt->status = status;
}
diff --git a/src/ss7_route.h b/src/ss7_route.h
index 2e35d1f..437a5d8 100644
--- a/src/ss7_route.h
+++ b/src/ss7_route.h
@@ -34,6 +34,8 @@
struct osmo_ss7_combined_linkset *clset;

enum osmo_ss7_route_status status;
+ /* T10: ITU Q.704 13.5.2 & rfc4666 4.5.3, ETSI TS 102 142 V1.1.1 */
+ struct osmo_timer_list t10_audit_timer;

struct {
/*! pointer to linkset (destination) of route */
diff --git a/tests/vty/osmo_stp_test.vty b/tests/vty/osmo_stp_test.vty
index 6e98bb4..561fc39 100644
--- a/tests/vty/osmo_stp_test.vty
+++ b/tests/vty/osmo_stp_test.vty
@@ -132,7 +132,7 @@
no as NAME
sccp-address NAME
no sccp-address NAME
- timer xua (T8) <1-999999>
+ timer xua (T8|T10) <1-999999>
listen (sua|m3ua|ipa) <0-65534> [(sctp|tcp)]
no listen (sua|m3ua|ipa) <0-65534> [(sctp|tcp)]
route-table system
diff --git a/tests/vty/ss7_asp_test.vty b/tests/vty/ss7_asp_test.vty
index ee6f9c2..62b7aa3 100644
--- a/tests/vty/ss7_asp_test.vty
+++ b/tests/vty/ss7_asp_test.vty
@@ -130,7 +130,7 @@
no as NAME
sccp-address NAME
no sccp-address NAME
- timer xua (T8) <1-999999>
+ timer xua (T8|T10) <1-999999>
listen (sua|m3ua|ipa) <0-65534> [(sctp|tcp)]
no listen (sua|m3ua|ipa) <0-65534> [(sctp|tcp)]
sccp-timer (conn_est|ias|iar|rel|repeat_rel|int|guard|reset|reassembly) <1-999999>

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

Gerrit-MessageType: merged
Gerrit-Project: libosmo-sigtran
Gerrit-Branch: master
Gerrit-Change-Id: Ic12b1aa8f2a02f32615dade34f0e1f01b2535f7b
Gerrit-Change-Number: 42506
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <pespin@sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: daniel <dwillmann@sysmocom.de>
Gerrit-Reviewer: fixeria <vyanitskiy@sysmocom.de>
Gerrit-Reviewer: laforge <laforge@osmocom.org>
Gerrit-Reviewer: osmith <osmith@sysmocom.de>