sccp: Use tdef to implement osmo_sccp_timers
Related: OS#4372 Change-Id: I1dbe49a83a1bcddf074d5e638babd065834a0ebd
This commit is contained in:
parent
1532791798
commit
c086a8ed42
|
@ -4,6 +4,7 @@
|
|||
#include <osmocom/core/prim.h>
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
#include <osmocom/core/linuxrbtree.h>
|
||||
#include <osmocom/core/tdef.h>
|
||||
#include <osmocom/sigtran/sccp_sap.h>
|
||||
#include <osmocom/sigtran/osmo_ss7.h>
|
||||
#include <osmocom/sigtran/protocol/mtp.h>
|
||||
|
@ -12,7 +13,8 @@
|
|||
|
||||
/* Appendix C.4 of Q.714 */
|
||||
enum osmo_sccp_timer {
|
||||
OSMO_SCCP_TIMER_CONN_EST,
|
||||
/* 0 kept unused on purpose since it's handled specially by osmo_fsm */
|
||||
OSMO_SCCP_TIMER_CONN_EST = 1,
|
||||
OSMO_SCCP_TIMER_IAS,
|
||||
OSMO_SCCP_TIMER_IAR,
|
||||
OSMO_SCCP_TIMER_REL,
|
||||
|
@ -22,24 +24,15 @@ enum osmo_sccp_timer {
|
|||
OSMO_SCCP_TIMER_RESET,
|
||||
OSMO_SCCP_TIMER_REASSEMBLY,
|
||||
/* This must remain the last item: */
|
||||
OSMO_SCCP_TIMERS_COUNT
|
||||
OSMO_SCCP_TIMERS_LEN
|
||||
};
|
||||
|
||||
struct osmo_sccp_timer_val {
|
||||
uint32_t s;
|
||||
uint32_t us;
|
||||
};
|
||||
|
||||
extern const struct osmo_sccp_timer_val osmo_sccp_timer_defaults[];
|
||||
extern const struct osmo_tdef osmo_sccp_timer_defaults[OSMO_SCCP_TIMERS_LEN];
|
||||
|
||||
extern const struct value_string osmo_sccp_timer_names[];
|
||||
static inline const char *osmo_sccp_timer_name(enum osmo_sccp_timer val)
|
||||
{ return get_value_string(osmo_sccp_timer_names, val); }
|
||||
|
||||
extern const struct value_string osmo_sccp_timer_descriptions[];
|
||||
static inline const char *osmo_sccp_timer_description(enum osmo_sccp_timer val)
|
||||
{ return get_value_string(osmo_sccp_timer_descriptions, val); }
|
||||
|
||||
/* an instance of the SCCP stack */
|
||||
struct osmo_sccp_instance {
|
||||
/* entry in global list of ss7 instances */
|
||||
|
@ -57,7 +50,7 @@ struct osmo_sccp_instance {
|
|||
|
||||
struct osmo_ss7_user ss7_user;
|
||||
|
||||
struct osmo_sccp_timer_val timers[OSMO_SCCP_TIMERS_COUNT];
|
||||
struct osmo_tdef *tdefs;
|
||||
|
||||
uint32_t max_optional_data;
|
||||
};
|
||||
|
@ -129,10 +122,6 @@ extern struct osmo_fsm sccp_scoc_fsm;
|
|||
|
||||
void sccp_scoc_show_connections(struct vty *vty, struct osmo_sccp_instance *inst);
|
||||
|
||||
const struct osmo_sccp_timer_val *osmo_sccp_timer_get(const struct osmo_sccp_instance *inst,
|
||||
enum osmo_sccp_timer timer,
|
||||
bool default_if_unset);
|
||||
|
||||
void osmo_sccp_vty_write_cs7_node(struct vty *vty, const char *indent, struct osmo_sccp_instance *inst);
|
||||
|
||||
/* Local Broadcast (LBCS) */
|
||||
|
|
110
src/sccp_scoc.c
110
src/sccp_scoc.c
|
@ -234,6 +234,31 @@ static const struct osmo_prim_event_map scu_scoc_event_map[] = {
|
|||
* Timer Handling
|
||||
***********************************************************************/
|
||||
|
||||
/* Mostly pasted from Appendix C.4 of ITU-T Q.714 (05/2001) -- some of their descriptions are quite
|
||||
* unintelligible out of context, for which we have our own description here. */
|
||||
const struct osmo_tdef osmo_sccp_timer_defaults[OSMO_SCCP_TIMERS_LEN] = {
|
||||
{ .T = OSMO_SCCP_TIMER_CONN_EST, .default_val = 1*60, .unit = OSMO_TDEF_S,
|
||||
.desc = "Waiting for connection confirm message, 1 to 2 minutes" },
|
||||
{ .T = OSMO_SCCP_TIMER_IAS, .default_val = 7*60, .unit = OSMO_TDEF_S,
|
||||
.desc = "Send keep-alive: on an idle connection, delay before sending an Idle Timer message, 5 to 10 minutes" }, /* RFC 3868 Ch. 8. */
|
||||
{ .T = OSMO_SCCP_TIMER_IAR, .default_val = 15*60, .unit = OSMO_TDEF_S,
|
||||
.desc = "Receive keep-alive: on an idle connection, delay until considering a connection as stale, 11 to 21 minutes" }, /* RFC 3868 Ch. 8. */
|
||||
{ .T = OSMO_SCCP_TIMER_REL, .default_val = 10, .unit = OSMO_TDEF_S,
|
||||
.desc = "Waiting for release complete message, 10 to 20 seconds" },
|
||||
{ .T = OSMO_SCCP_TIMER_REPEAT_REL, .default_val = 10, .unit = OSMO_TDEF_S,
|
||||
.desc = "Waiting for release complete message; or to repeat sending released message after the initial expiry, 10 to 20 seconds" },
|
||||
{ .T = OSMO_SCCP_TIMER_INT, .default_val = 1*60, .unit = OSMO_TDEF_S,
|
||||
.desc = "Waiting for release complete message; or to release connection resources, freeze the LRN and "
|
||||
"alert a maintenance function after the initial expiry, extending to 1 minute" },
|
||||
{ .T = OSMO_SCCP_TIMER_GUARD, .default_val = 23*60, .unit = OSMO_TDEF_S,
|
||||
.desc = "Waiting to resume normal procedure for temporary connection sections during the restart procedure, 23 to 25 minutes" },
|
||||
{ .T = OSMO_SCCP_TIMER_RESET, .default_val = 10, .unit = OSMO_TDEF_S,
|
||||
.desc = "Waiting to release temporary connection section or alert maintenance function after reset request message is sent, 10 to 20 seconds" },
|
||||
{ .T = OSMO_SCCP_TIMER_REASSEMBLY, .default_val = 10, .unit = OSMO_TDEF_S,
|
||||
.desc = "Waiting to receive all the segments of the remaining segments, single segmented message after receiving the first segment, 10 to 20 seconds" },
|
||||
{}
|
||||
};
|
||||
|
||||
/* Appendix C.4 of ITU-T Q.714 */
|
||||
const struct value_string osmo_sccp_timer_names[] = {
|
||||
{ OSMO_SCCP_TIMER_CONN_EST, "conn_est" },
|
||||
|
@ -248,93 +273,16 @@ const struct value_string osmo_sccp_timer_names[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
/* Mostly pasted from Appendix C.4 of ITU-T Q.714 (05/2001) -- some of their descriptions are quite
|
||||
* unintelligible out of context, for which we have our own description here. */
|
||||
const struct value_string osmo_sccp_timer_descriptions[] = {
|
||||
{ OSMO_SCCP_TIMER_CONN_EST,
|
||||
"Waiting for connection confirm message, 1 to 2 minutes" },
|
||||
{ OSMO_SCCP_TIMER_IAS,
|
||||
"Send keep-alive: on an idle connection, delay before sending an Idle Timer message,"
|
||||
" 5 to 10 minutes" },
|
||||
{ OSMO_SCCP_TIMER_IAR,
|
||||
"Receive keep-alive: on an idle connection, delay until considering a connection as stale,"
|
||||
" 11 to 21 minutes" },
|
||||
{ OSMO_SCCP_TIMER_REL,
|
||||
"Waiting for release complete message, 10 to 20 seconds" },
|
||||
{ OSMO_SCCP_TIMER_REPEAT_REL,
|
||||
"Waiting for release complete message; or to repeat sending released message after the initial"
|
||||
" expiry, 10 to 20 seconds" },
|
||||
{ OSMO_SCCP_TIMER_INT,
|
||||
"Waiting for release complete message; or to release connection resources, freeze the LRN and"
|
||||
" alert a maintenance function after the initial expiry, extending to 1 minute" },
|
||||
{ OSMO_SCCP_TIMER_GUARD,
|
||||
"Waiting to resume normal procedure for temporary connection sections during the restart"
|
||||
" procedure, 23 to 25 minutes" },
|
||||
{ OSMO_SCCP_TIMER_RESET,
|
||||
"Waiting to release temporary connection section or alert maintenance function after reset"
|
||||
" request message is sent, 10 to 20 seconds" },
|
||||
{ OSMO_SCCP_TIMER_REASSEMBLY,
|
||||
"Waiting to receive all the segments of the remaining segments, single segmented message after"
|
||||
" receiving the first segment, 10 to 20 seconds" },
|
||||
{}
|
||||
};
|
||||
|
||||
/* Appendix C.4 of ITU-T Q.714 */
|
||||
const struct osmo_sccp_timer_val osmo_sccp_timer_defaults[] = {
|
||||
[OSMO_SCCP_TIMER_CONN_EST] = { .s = 1 * 60, },
|
||||
[OSMO_SCCP_TIMER_IAS] = { .s = 7 * 60, }, /* RFC 3868 Ch. 8. */
|
||||
[OSMO_SCCP_TIMER_IAR] = { .s = 15 * 60, }, /* RFC 3868 Ch. 8. */
|
||||
[OSMO_SCCP_TIMER_REL] = { .s = 10, },
|
||||
[OSMO_SCCP_TIMER_REPEAT_REL] = { .s = 10, },
|
||||
[OSMO_SCCP_TIMER_INT] = { .s = 1 * 60, },
|
||||
[OSMO_SCCP_TIMER_GUARD] = { .s = 23 * 60, },
|
||||
[OSMO_SCCP_TIMER_RESET] = { .s = 10, },
|
||||
[OSMO_SCCP_TIMER_REASSEMBLY] = { .s = 10, },
|
||||
};
|
||||
|
||||
osmo_static_assert(ARRAY_SIZE(osmo_sccp_timer_defaults) == OSMO_SCCP_TIMERS_COUNT,
|
||||
osmo_static_assert(ARRAY_SIZE(osmo_sccp_timer_defaults) == (OSMO_SCCP_TIMERS_LEN) &&
|
||||
ARRAY_SIZE(osmo_sccp_timer_names) == (OSMO_SCCP_TIMERS_LEN),
|
||||
assert_osmo_sccp_timers_count);
|
||||
|
||||
/* Look up an SCCP timer value as configured in the osmo_ss7_instance.
|
||||
* If no user defined value is set, return the global default from osmo_sccp_timer_defaults instead.
|
||||
* However, if default_if_unset is passed false, return NULL in case there is no user defined setting, or
|
||||
* in case it is identical to the global default. */
|
||||
const struct osmo_sccp_timer_val *osmo_sccp_timer_get(const struct osmo_sccp_instance *inst,
|
||||
enum osmo_sccp_timer timer,
|
||||
bool default_if_unset)
|
||||
{
|
||||
const struct osmo_sccp_timer_val *val;
|
||||
const struct osmo_sccp_timer_val *def;
|
||||
|
||||
OSMO_ASSERT(timer >= 0
|
||||
&& timer < ARRAY_SIZE(inst->timers)
|
||||
&& timer < ARRAY_SIZE(osmo_sccp_timer_defaults));
|
||||
|
||||
val = &inst->timers[timer];
|
||||
def = &osmo_sccp_timer_defaults[timer];
|
||||
|
||||
/* Assert that all timer definitions have a sane global default */
|
||||
OSMO_ASSERT(def->s || def->us);
|
||||
|
||||
if (val->s || val->us) {
|
||||
if (!default_if_unset && val->s == def->s && val->us == def->us)
|
||||
return NULL;
|
||||
return val;
|
||||
}
|
||||
|
||||
if (!default_if_unset)
|
||||
return NULL;
|
||||
|
||||
/* If unset, use the global default. */
|
||||
return def;
|
||||
}
|
||||
|
||||
static void sccp_timer_schedule(const struct sccp_connection *conn,
|
||||
struct osmo_timer_list *timer,
|
||||
enum osmo_sccp_timer timer_name)
|
||||
{
|
||||
const struct osmo_sccp_timer_val *val = osmo_sccp_timer_get(conn->inst, timer_name, true);
|
||||
osmo_timer_schedule(timer, val->s, val->us);
|
||||
const unsigned long val_sec = osmo_tdef_get(conn->inst->tdefs, timer_name, OSMO_TDEF_S, -1);
|
||||
osmo_timer_schedule(timer, val_sec, 0);
|
||||
}
|
||||
|
||||
/* T(ias) has expired, send a COIT message to the peer */
|
||||
|
|
|
@ -238,6 +238,10 @@ osmo_sccp_instance_create(struct osmo_ss7_instance *ss7, void *priv)
|
|||
inst->ss7_user.priv = inst;
|
||||
inst->max_optional_data = SCCP_MAX_OPTIONAL_DATA;
|
||||
|
||||
inst->tdefs = talloc_memdup(inst, osmo_sccp_timer_defaults,
|
||||
sizeof(osmo_sccp_timer_defaults));
|
||||
osmo_tdefs_reset(inst->tdefs);
|
||||
|
||||
rc = sccp_scmg_init(inst);
|
||||
if (rc < 0) {
|
||||
talloc_free(inst);
|
||||
|
|
|
@ -150,9 +150,8 @@ DEFUN_ATTR(sccp_timer, sccp_timer_cmd,
|
|||
{
|
||||
struct osmo_ss7_instance *ss7 = vty->index;
|
||||
enum osmo_sccp_timer timer = get_string_value(osmo_sccp_timer_names, argv[0]);
|
||||
struct osmo_sccp_timer_val set_val = { .s = atoi(argv[1]) };
|
||||
|
||||
if (timer < 0 || timer >= OSMO_SCCP_TIMERS_COUNT) {
|
||||
if (timer <= 0 || timer >= OSMO_SCCP_TIMERS_LEN) {
|
||||
vty_out(vty, "%% Invalid timer: %s%s", argv[0], VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
@ -163,7 +162,8 @@ DEFUN_ATTR(sccp_timer, sccp_timer_cmd,
|
|||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
ss7->sccp->timers[timer] = set_val;
|
||||
OSMO_ASSERT(ss7->sccp->tdefs);
|
||||
osmo_tdef_set(ss7->sccp->tdefs, timer, atoi(argv[1]), OSMO_TDEF_S);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -197,14 +197,6 @@ DEFUN_ATTR(sccp_max_optional_data, sccp_max_optional_data_cmd,
|
|||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static const char *osmo_sccp_timer_val_name(const struct osmo_sccp_timer_val *val)
|
||||
{
|
||||
static char buf[16];
|
||||
|
||||
snprintf(buf, sizeof(buf), "%u", val->s);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void gen_sccp_timer_cmd_strs(struct cmd_element *cmd)
|
||||
{
|
||||
int i;
|
||||
|
@ -219,19 +211,19 @@ static void gen_sccp_timer_cmd_strs(struct cmd_element *cmd)
|
|||
"Configure SCCP timer values, see ITU-T Q.714\n");
|
||||
|
||||
for (i = 0; osmo_sccp_timer_names[i].str; i++) {
|
||||
const struct osmo_sccp_timer_val *def;
|
||||
const struct osmo_tdef *def;
|
||||
enum osmo_sccp_timer timer;
|
||||
|
||||
timer = osmo_sccp_timer_names[i].value;
|
||||
def = &osmo_sccp_timer_defaults[timer];
|
||||
OSMO_ASSERT(timer >= 0 && timer < OSMO_SCCP_TIMERS_COUNT);
|
||||
def = osmo_tdef_get_entry((struct osmo_tdef *)&osmo_sccp_timer_defaults, timer);
|
||||
OSMO_ASSERT(def);
|
||||
|
||||
osmo_talloc_asprintf(tall_vty_ctx, cmd_str, "%s%s",
|
||||
i ? "|" : "",
|
||||
osmo_sccp_timer_name(timer));
|
||||
osmo_talloc_asprintf(tall_vty_ctx, doc_str, "%s (default: %s)\n",
|
||||
osmo_sccp_timer_description(timer),
|
||||
osmo_sccp_timer_val_name(def));
|
||||
osmo_sccp_timer_names[i].str);
|
||||
osmo_talloc_asprintf(tall_vty_ctx, doc_str, "%s (default: %lu)\n",
|
||||
def->desc,
|
||||
def->default_val);
|
||||
}
|
||||
|
||||
osmo_talloc_asprintf(tall_vty_ctx, cmd_str, ") <1-999999>");
|
||||
|
@ -247,12 +239,14 @@ static void write_sccp_timers(struct vty *vty, const char *indent,
|
|||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(inst->timers); i++) {
|
||||
const struct osmo_sccp_timer_val *val = osmo_sccp_timer_get(inst, i, default_if_unset);
|
||||
if (!val)
|
||||
for (i = 0; osmo_sccp_timer_names[i].str; i++) {
|
||||
const struct osmo_tdef *tdef = osmo_tdef_get_entry(inst->tdefs, osmo_sccp_timer_names[i].value);
|
||||
if (!tdef)
|
||||
continue;
|
||||
vty_out(vty, "%ssccp-timer %s %s%s", indent, osmo_sccp_timer_name(i),
|
||||
osmo_sccp_timer_val_name(val), VTY_NEWLINE);
|
||||
if (!default_if_unset && tdef->val == tdef->default_val)
|
||||
continue;
|
||||
vty_out(vty, "%ssccp-timer %s %lu%s", indent, osmo_sccp_timer_names[i].str,
|
||||
tdef->val, VTY_NEWLINE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue