diff options
author | Pau Espin Pedrol <pespin@sysmocom.de> | 2023-07-07 18:00:46 +0200 |
---|---|---|
committer | Pau Espin Pedrol <pespin@sysmocom.de> | 2023-07-11 14:56:26 +0200 |
commit | 4ddaee93624d1677ff96c35a2f9a91bd57d6b882 (patch) | |
tree | d87cda41cf1f45ea3ba3141bee1601cf30dc5e0b | |
parent | 5cf725b1915996a1f068b379eaa86a6278157af6 (diff) |
asp: Make ASP default LM timers VTY configurable
Related: SYS#6511
Change-Id: Ib62e19f2e528e8b2792cbb51a5900dc3463ebd06
-rw-r--r-- | include/osmocom/sigtran/osmo_ss7.h | 3 | ||||
-rw-r--r-- | src/osmo_ss7.c | 5 | ||||
-rw-r--r-- | src/osmo_ss7_vty.c | 74 | ||||
-rw-r--r-- | src/xua_default_lm_fsm.c | 78 | ||||
-rw-r--r-- | src/xua_internal.h | 17 |
5 files changed, 157 insertions, 20 deletions
diff --git a/include/osmocom/sigtran/osmo_ss7.h b/include/osmocom/sigtran/osmo_ss7.h index 3c72394..ba1e214 100644 --- a/include/osmocom/sigtran/osmo_ss7.h +++ b/include/osmocom/sigtran/osmo_ss7.h @@ -437,6 +437,9 @@ struct osmo_ss7_asp { struct osmo_ss7_asp_peer remote; uint8_t qos_class; uint32_t quirks; + + /* T_defs used by the default_lm: */ + struct osmo_tdef *T_defs_lm; } cfg; }; diff --git a/src/osmo_ss7.c b/src/osmo_ss7.c index 839d756..e24b853 100644 --- a/src/osmo_ss7.c +++ b/src/osmo_ss7.c @@ -1538,6 +1538,11 @@ osmo_ss7_asp_alloc(struct osmo_ss7_instance *inst, const char *name, asp->cfg.local.port = local_port; asp->cfg.proto = proto; asp->cfg.name = talloc_strdup(asp, name); + + asp->cfg.T_defs_lm = talloc_memdup(asp, ss7_asp_lm_timer_defaults, + sizeof(ss7_asp_lm_timer_defaults)); + osmo_tdefs_reset(asp->cfg.T_defs_lm); + llist_add_tail(&asp->list, &inst->asp_list); /* The SUA code internally needs SCCP to work */ diff --git a/src/osmo_ss7_vty.c b/src/osmo_ss7_vty.c index 9398bc1..61f14cd 100644 --- a/src/osmo_ss7_vty.c +++ b/src/osmo_ss7_vty.c @@ -790,6 +790,77 @@ DEFUN_ATTR(asp_no_quirk, asp_no_quirk_cmd, return CMD_SUCCESS; } +/* timer lm <name> <1-999999> + * (cmdstr and doc are dynamically generated from ss7_asp_lm_timer_names.) */ +DEFUN_ATTR(asp_timer, asp_timer_cmd, + NULL, NULL, CMD_ATTR_IMMEDIATE) +{ + struct osmo_ss7_asp *asp = vty->index; + enum ss7_asp_lm_timer timer = get_string_value(ss7_asp_lm_timer_names, argv[0]); + + if (timer <= 0 || timer >= SS7_ASP_LM_TIMERS_LEN) { + vty_out(vty, "%% Invalid timer: %s%s", argv[0], VTY_NEWLINE); + return CMD_WARNING; + } + + osmo_tdef_set(asp->cfg.T_defs_lm, timer, atoi(argv[1]), OSMO_TDEF_S); + return CMD_SUCCESS; +} + +static void gen_asp_timer_cmd_strs(struct cmd_element *cmd) +{ + int i; + char *cmd_str = NULL; + char *doc_str = NULL; + + OSMO_ASSERT(cmd->string == NULL); + OSMO_ASSERT(cmd->doc == NULL); + + osmo_talloc_asprintf(tall_vty_ctx, cmd_str, "timer lm ("); + osmo_talloc_asprintf(tall_vty_ctx, doc_str, + "Configure ASP default timer values\n" + "Configure ASP default lm timer values\n"); + + for (i = 0; ss7_asp_lm_timer_names[i].str; i++) { + const struct osmo_tdef *def; + enum ss7_asp_lm_timer timer; + + timer = ss7_asp_lm_timer_names[i].value; + def = osmo_tdef_get_entry((struct osmo_tdef *)&ss7_asp_lm_timer_defaults, timer); + OSMO_ASSERT(def); + + osmo_talloc_asprintf(tall_vty_ctx, cmd_str, "%s%s", + i ? "|" : "", + ss7_asp_lm_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>"); + osmo_talloc_asprintf(tall_vty_ctx, doc_str, + "Timer value, in seconds\n"); + + cmd->string = cmd_str; + cmd->doc = doc_str; +} + +static void write_asp_timers(struct vty *vty, const char *indent, + struct osmo_ss7_asp *asp) +{ + int i; + + for (i = 0; ss7_asp_lm_timer_names[i].str; i++) { + const struct osmo_tdef *tdef = osmo_tdef_get_entry(asp->cfg.T_defs_lm, ss7_asp_lm_timer_names[i].value); + if (!tdef) + continue; + if (tdef->val == tdef->default_val) + continue; + vty_out(vty, "%stimer lm %s %lu%s", indent, ss7_asp_lm_timer_names[i].str, + tdef->val, VTY_NEWLINE); + } +} + static char *as_list_for_asp(const struct osmo_ss7_asp *asp, char *buf, size_t buf_len) { struct osmo_strbuf sb = { .buf = buf, .len = buf_len }; @@ -882,6 +953,7 @@ static void write_one_asp(struct vty *vty, struct osmo_ss7_asp *asp, bool show_d continue; vty_out(vty, " quirk %s%s", get_value_string(asp_quirk_names, (1 << i)), VTY_NEWLINE); } + write_asp_timers(vty, " ", asp); } @@ -2127,6 +2199,8 @@ static void vty_init_shared(void *ctx) install_lib_element(L_CS7_ASP_NODE, &asp_shutdown_cmd); install_lib_element(L_CS7_ASP_NODE, &asp_quirk_cmd); install_lib_element(L_CS7_ASP_NODE, &asp_no_quirk_cmd); + gen_asp_timer_cmd_strs(&asp_timer_cmd); + install_lib_element(L_CS7_ASP_NODE, &asp_timer_cmd); install_node(&as_node, NULL); install_lib_element_ve(&show_cs7_as_cmd); diff --git a/src/xua_default_lm_fsm.c b/src/xua_default_lm_fsm.c index 512c6c4..639d30a 100644 --- a/src/xua_default_lm_fsm.c +++ b/src/xua_default_lm_fsm.c @@ -76,17 +76,53 @@ static const struct value_string lm_event_names[] = { { 0, NULL } }; -enum lm_timer { - T_WAIT_ASP_UP, - T_WAIT_NOTIFY, - T_WAIT_NOTIFY_RKM, - T_WAIT_RK_REG_RESP, +/*********************************************************************** + * Timer Handling + ***********************************************************************/ + +const struct osmo_tdef ss7_asp_lm_timer_defaults[SS7_ASP_LM_TIMERS_LEN] = { + { .T = SS7_ASP_LM_T_WAIT_ASP_UP, .default_val = 20, .unit = OSMO_TDEF_S, + .desc = "Restart ASP after timeout waiting for ASP UP (SG role) / ASP UP ACK (ASP role) (s)" }, + { .T = SS7_ASP_LM_T_WAIT_NOTIFY, .default_val = 2, .unit = OSMO_TDEF_S, + .desc = "Restart ASP after timeout waiting for NOTIFY (s)" }, + { .T = SS7_ASP_LM_T_WAIT_NOTIY_RKM, .default_val = 20, .unit = OSMO_TDEF_S, + .desc = "Restart ASP after timeout waiting for NOTIFY after RKM registration (s)" }, + { .T = SS7_ASP_LM_T_WAIT_RK_REG_RESP, .default_val = 10, .unit = OSMO_TDEF_S, + .desc = "Restart ASP after timeout waiting for RK_REG_RESP (s)" }, + {} +}; + +/* Appendix C.4 of ITU-T Q.714 */ +const struct value_string ss7_asp_lm_timer_names[] = { + { SS7_ASP_LM_T_WAIT_ASP_UP, "wait_asp_up" }, + { SS7_ASP_LM_T_WAIT_NOTIFY, "wait_notify" }, + { SS7_ASP_LM_T_WAIT_NOTIY_RKM, "wait_notify_rkm" }, + { SS7_ASP_LM_T_WAIT_RK_REG_RESP, "wait_rk_reg_resp" }, + {} +}; + +osmo_static_assert(ARRAY_SIZE(ss7_asp_lm_timer_defaults) == (SS7_ASP_LM_TIMERS_LEN) && + ARRAY_SIZE(ss7_asp_lm_timer_names) == (SS7_ASP_LM_TIMERS_LEN), + assert_ss7_asp_lm_timer_count); + +static const struct osmo_tdef_state_timeout lm_fsm_timeouts[32] = { + [S_IDLE] = { }, + [S_WAIT_ASP_UP] = { .T = SS7_ASP_LM_T_WAIT_ASP_UP }, + [S_WAIT_NOTIFY] = { .T = SS7_ASP_LM_T_WAIT_NOTIFY }, /* SS7_ASP_LM_T_WAIT_NOTIY_RKM if coming from S_RKM_REG */ + [S_RKM_REG] = { .T = SS7_ASP_LM_T_WAIT_RK_REG_RESP }, + [S_ACTIVE] = { }, }; struct lm_fsm_priv { struct osmo_ss7_asp *asp; }; +#define lm_fsm_state_chg(fi, NEXT_STATE) \ + osmo_tdef_fsm_inst_state_chg(fi, NEXT_STATE, \ + lm_fsm_timeouts, \ + ((struct lm_fsm_priv *)(fi->priv))->asp->cfg.T_defs_lm, \ + -1) + static struct osmo_ss7_as *find_first_as_in_asp(struct osmo_ss7_asp *asp) { struct osmo_ss7_as *as; @@ -138,8 +174,8 @@ static void lm_idle(struct osmo_fsm_inst *fi, uint32_t event, void *data) switch (event) { case LM_E_SCTP_EST_IND: - /* Try to transition to ASP-UP, wait for 20s */ - osmo_fsm_inst_state_chg(fi, S_WAIT_ASP_UP, 20, T_WAIT_ASP_UP); + /* Try to transition to ASP-UP, wait to receive message for a few seconds */ + lm_fsm_state_chg(fi, S_WAIT_ASP_UP); osmo_fsm_inst_dispatch(lmp->asp->fi, XUA_ASP_E_M_ASP_UP_REQ, NULL); break; } @@ -151,7 +187,7 @@ static void lm_wait_asp_up(struct osmo_fsm_inst *fi, uint32_t event, void *data) case LM_E_ASP_UP_CONF: /* ASP is up, wait for some time if any NOTIFY * indications about AS in this ASP are received */ - osmo_fsm_inst_state_chg(fi, S_WAIT_NOTIFY, 2, T_WAIT_NOTIFY); + lm_fsm_state_chg(fi, S_WAIT_NOTIFY); break; } } @@ -164,13 +200,13 @@ static int lm_timer_cb(struct osmo_fsm_inst *fi) struct osmo_ss7_as *as; switch (fi->T) { - case T_WAIT_ASP_UP: + case SS7_ASP_LM_T_WAIT_ASP_UP: /* we have been waiting for the ASP to come up, but it * failed to do so */ LOGPFSML(fi, LOGL_NOTICE, "Peer didn't send any ASP_UP in time! Restarting ASP\n"); restart_asp(fi); break; - case T_WAIT_NOTIFY: + case SS7_ASP_LM_T_WAIT_NOTIFY: if (lmp->asp->cfg.quirks & OSMO_SS7_ASP_QUIRK_NO_NOTIFY) { /* some implementations don't send the NOTIFY which they SHOULD * according to RFC4666 (see OS#5145) */ @@ -181,7 +217,7 @@ static int lm_timer_cb(struct osmo_fsm_inst *fi) /* No AS has reported via NOTIFY that is was * (statically) configured at the SG for this ASP, so * let's dynamically register */ - osmo_fsm_inst_state_chg(fi, S_RKM_REG, 10, T_WAIT_RK_REG_RESP); + lm_fsm_state_chg(fi, S_RKM_REG); prim = xua_xlm_prim_alloc(OSMO_XLM_PRIM_M_RK_REG, PRIM_OP_REQUEST); OSMO_ASSERT(prim); as = find_first_as_in_asp(lmp->asp); @@ -195,12 +231,12 @@ static int lm_timer_cb(struct osmo_fsm_inst *fi) prim->u.rk_reg.traf_mode = as->cfg.mode; osmo_xlm_sap_down(lmp->asp, &prim->oph); break; - case T_WAIT_NOTIFY_RKM: + case SS7_ASP_LM_T_WAIT_NOTIY_RKM: /* No AS has reported via NOTIFY even after dynamic RKM * configuration */ restart_asp(fi); break; - case T_WAIT_RK_REG_RESP: + case SS7_ASP_LM_T_WAIT_RK_REG_RESP: /* timeout of registration of routing key */ restart_asp(fi); break; @@ -220,7 +256,7 @@ static void lm_wait_notify(struct osmo_fsm_inst *fi, uint32_t event, void *data) if (oxp->u.notify.status_type == M3UA_NOTIFY_T_STATCHG && (oxp->u.notify.status_info == M3UA_NOTIFY_I_AS_INACT || oxp->u.notify.status_info == M3UA_NOTIFY_I_AS_PEND)) { - osmo_fsm_inst_state_chg(fi, S_ACTIVE, 0, 0); + lm_fsm_state_chg(fi, S_ACTIVE); osmo_fsm_inst_dispatch(lmp->asp->fi, XUA_ASP_E_M_ASP_ACTIVE_REQ, NULL); } break; @@ -229,7 +265,7 @@ static void lm_wait_notify(struct osmo_fsm_inst *fi, uint32_t event, void *data) * the SG, and that this AS is currently inactive */ /* request the ASP to go into active state (which * hopefully will bring the AS to active, too) */ - osmo_fsm_inst_state_chg(fi, S_ACTIVE, 0, 0); + lm_fsm_state_chg(fi, S_ACTIVE); osmo_fsm_inst_dispatch(lmp->asp->fi, XUA_ASP_E_M_ASP_ACTIVE_REQ, NULL); break; } @@ -237,6 +273,7 @@ static void lm_wait_notify(struct osmo_fsm_inst *fi, uint32_t event, void *data) static void lm_rkm_reg(struct osmo_fsm_inst *fi, uint32_t event, void *data) { + struct lm_fsm_priv *lmp = fi->priv; struct osmo_xlm_prim *oxp; int rc; @@ -247,14 +284,15 @@ static void lm_rkm_reg(struct osmo_fsm_inst *fi, uint32_t event, void *data) LOGPFSML(fi, LOGL_NOTICE, "Received RKM_REG_RSP with negative result\n"); restart_asp(fi); } else { + unsigned long timeout_sec; rc = handle_reg_conf(fi, oxp->u.rk_reg.key.l_rk_id, oxp->u.rk_reg.key.context); if (rc < 0) restart_asp(fi); - /* RKM registration was successful, we can - * transition to WAIT_NOTIFY state and assume - * that an NOTIFY/AS-INACTIVE arrives within 20 - * seconds */ - osmo_fsm_inst_state_chg(fi, S_WAIT_NOTIFY, 20, T_WAIT_NOTIFY_RKM); + /* RKM registration was successful, we can transition to WAIT_NOTIFY + * state and assume that an NOTIFY/AS-INACTIVE arrives within + * T_WAIT_NOTIFY_RKM seconds */ + timeout_sec = osmo_tdef_get(lmp->asp->cfg.T_defs_lm, SS7_ASP_LM_T_WAIT_NOTIY_RKM, OSMO_TDEF_S, -1); + osmo_fsm_inst_state_chg(fi, S_WAIT_NOTIFY, timeout_sec, SS7_ASP_LM_T_WAIT_NOTIY_RKM); } break; } diff --git a/src/xua_internal.h b/src/xua_internal.h index 5dd7066..26cb3fc 100644 --- a/src/xua_internal.h +++ b/src/xua_internal.h @@ -1,5 +1,6 @@ #pragma once +#include <osmocom/core/tdef.h> #include <osmocom/sigtran/osmo_ss7.h> #include <osmocom/sigtran/xua_msg.h> @@ -85,6 +86,22 @@ void xua_asp_send_xlm_prim_simple(struct osmo_ss7_asp *asp, void xua_snm_pc_available(struct osmo_ss7_as *as, const uint32_t *aff_pc, unsigned int num_aff_pc, const char *info_str, bool available); +enum ss7_asp_lm_timer { + /* 0 kept unused on purpose since it's handled specially by osmo_fsm */ + SS7_ASP_LM_T_WAIT_ASP_UP = 1, + SS7_ASP_LM_T_WAIT_NOTIFY, + SS7_ASP_LM_T_WAIT_NOTIY_RKM, + SS7_ASP_LM_T_WAIT_RK_REG_RESP, + /* This must remain the last item: */ + SS7_ASP_LM_TIMERS_LEN +}; + +extern const struct osmo_tdef ss7_asp_lm_timer_defaults[SS7_ASP_LM_TIMERS_LEN]; + +extern const struct value_string ss7_asp_lm_timer_names[]; +static inline const char *ss7_asp_lm_timer_name(enum ss7_asp_lm_timer val) +{ return get_value_string(ss7_asp_lm_timer_names, val); } + extern struct osmo_fsm xua_default_lm_fsm; extern const struct value_string m3ua_rkm_reg_status_vals[]; extern const struct value_string m3ua_rkm_dereg_status_vals[]; |