WIP: rate counters for SCCP stack

TODO:
* testing

Change-Id: I79df56d956aaf7dee1c4f879097100e39347e44d
This commit is contained in:
Harald Welte 2023-03-23 23:18:08 +01:00
parent ba1e74c4f4
commit 0868503688
4 changed files with 124 additions and 1 deletions

View File

@ -4,12 +4,36 @@
#include <osmocom/core/prim.h>
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/linuxrbtree.h>
#include <osmocom/core/rate_ctr.h>
#include <osmocom/sigtran/sccp_sap.h>
#include <osmocom/sigtran/osmo_ss7.h>
#include <osmocom/sigtran/protocol/mtp.h>
#define SCCP_STR "Signalling Connection Control Part\n"
enum sccp_user_ctr {
SCU_CTR_CLDT_OUT_COUNT,
SCU_CTR_CLDT_OUT_BYTES,
SCU_CTR_CLDT_IN_COUNT,
SCU_CTR_CLDT_IN_BYTES,
SCU_CTR_CONN_DISC_TIAR_EXP, /* number of T(iar) expirations (peer dead) */
SCU_CTR_CONN_OUT_REQ, /* number of outgoing SCCP connections requested */
SCU_CTR_CONN_OUT_EST, /* number of outgoing SCCP connections established */
SCU_CTR_CONN_OUT_TIMEOUT,
SCU_CTR_CONN_OUT_CREF,
SCU_CTR_CONN_OUT_RLSD,
SCU_CTR_CONN_OUT_DATA_COUNT,
SCU_CTR_CONN_OUT_DATA_BYTES,
SCU_CTR_CONN_IN_REQ, /* number of incoming SCCP connections requested */
SCU_CTR_CONN_IN_EST, /* number of incoming SCCP connections requested */
SCU_CTR_CONN_IN_CREF,
SCU_CTR_CONN_IN_DATA_COUNT,
SCU_CTR_CONN_IN_DATA_BYTES,
};
/* Appendix C.4 of Q.714 */
enum osmo_sccp_timer {
OSMO_SCCP_TIMER_CONN_EST,
@ -81,6 +105,9 @@ struct osmo_sccp_user {
/* Application Server FSM Instance */
struct osmo_fsm_inst *as_fi;
/* Rate counters for this user */
struct rate_ctr_group *ctrg;
};
extern int DSCCP;

View File

@ -130,6 +130,8 @@ int sccp_sclc_user_sap_down_nofree(struct osmo_sccp_user *scu, struct osmo_prim_
switch (OSMO_PRIM_HDR(&prim->oph)) {
case OSMO_PRIM(OSMO_SCU_PRIM_N_UNITDATA, PRIM_OP_REQUEST):
/* Connectionless by-passes this altogether */
rate_ctr_inc2(scu->ctrg, SCU_CTR_CLDT_OUT_COUNT);
rate_ctr_add2(scu->ctrg, SCU_CTR_CLDT_OUT_BYTES, msgb_l2len(prim->oph.msg));
return xua_gen_encode_and_send(scu, -1, prim, SUA_CL_CLDT);
default:
LOGP(DLSCCP, LOGL_ERROR, "Received unknown SCCP User "
@ -192,6 +194,9 @@ static int sclc_rx_cldt(struct osmo_sccp_instance *inst, struct xua_msg *xua)
return 0;
}
rate_ctr_inc2(scu->ctrg, SCU_CTR_CLDT_IN_COUNT);
rate_ctr_add2(scu->ctrg, SCU_CTR_CLDT_IN_BYTES, data_ie->len);
/* copy data */
upmsg->l2h = msgb_put(upmsg, data_ie->len);
memcpy(upmsg->l2h, data_ie->dat, data_ie->len);

View File

@ -846,6 +846,12 @@ static struct xua_msg *xua_gen_msg_co(struct sccp_connection *conn, uint32_t eve
xua_msg_free(xua);
return NULL;
}
if (encode_opt_data) {
rate_ctr_inc2(conn->user->ctrg, SCU_CTR_CONN_OUT_DATA_COUNT);
rate_ctr_add2(conn->user->ctrg, SCU_CTR_CONN_OUT_DATA_BYTES, msgb_l2len(prim->oph.msg));
}
return xua;
prim_needed:
@ -972,6 +978,11 @@ static void scu_gen_encode_and_send(struct sccp_connection *conn, uint32_t event
return;
}
if (msgb_l2(scu_prim->oph.msg)) {
rate_ctr_inc2(conn->user->ctrg, SCU_CTR_CONN_IN_DATA_COUNT);
rate_ctr_add2(conn->user->ctrg, SCU_CTR_CONN_IN_DATA_BYTES, msgb_l2len(scu_prim->oph.msg));
}
sccp_user_prim_up(conn->user, scu_prim);
}
@ -993,11 +1004,12 @@ static void scoc_fsm_idle(struct osmo_fsm_inst *fi, uint32_t event, void *data)
case SCOC_E_SCU_N_CONN_REQ:
prim = data;
uconp = &prim->u.connect;
/* generate + send CR PDU to SCRC */
/* copy relevant parameters from prim to conn */
conn->called_addr = uconp->called_addr;
conn->calling_addr = uconp->calling_addr;
conn->sccp_class = uconp->sccp_class;
/* generate + send CR PDU to SCRC */
rate_ctr_inc2(conn->user->ctrg, SCU_CTR_CONN_OUT_REQ);
rc = xua_gen_encode_and_send(conn, event, prim, SUA_CO_CORE);
if (rc < 0)
LOGPFSML(fi, LOGL_ERROR, "Failed to initiate connection: %s\n", strerror(-rc));
@ -1030,6 +1042,7 @@ static void scoc_fsm_idle(struct osmo_fsm_inst *fi, uint32_t event, void *data)
/* Figure C.3 / Q.714 (sheet 1 of 6) */
case SCOC_E_RCOC_CONN_IND:
xua = data;
rate_ctr_inc2(conn->user->ctrg, SCU_CTR_CONN_IN_REQ);
/* copy relevant parameters from xua to conn */
sua_addr_parse(&conn->calling_addr, xua, SUA_IEI_SRC_ADDR);
sua_addr_parse(&conn->called_addr, xua, SUA_IEI_DEST_ADDR);
@ -1070,6 +1083,7 @@ static void scoc_fsm_conn_pend_in(struct osmo_fsm_inst *fi, uint32_t event, void
switch (event) {
case SCOC_E_SCU_N_CONN_RESP:
prim = data;
rate_ctr_inc2(conn->user->ctrg, SCU_CTR_CONN_IN_EST);
/* FIXME: assign local reference (only now?) */
/* FIXME: assign sls, protocol class and credit */
xua_gen_encode_and_send(conn, event, prim, SUA_CO_COAK);
@ -1080,6 +1094,7 @@ static void scoc_fsm_conn_pend_in(struct osmo_fsm_inst *fi, uint32_t event, void
break;
case SCOC_E_SCU_N_DISC_REQ:
prim = data;
rate_ctr_inc2(conn->user->ctrg, SCU_CTR_CONN_IN_CREF);
/* release resources: implicit */
xua_gen_encode_and_send(conn, event, prim, SUA_CO_COREF);
/* N. B: we've ignored CREF sending errors as there's no recovery option anyway */
@ -1103,6 +1118,7 @@ static void scoc_fsm_conn_pend_out(struct osmo_fsm_inst *fi, uint32_t event, voi
/* keep conn timer running(!) */
break;
case SCOC_E_CONN_TMR_EXP:
rate_ctr_inc2(conn->user->ctrg, SCU_CTR_CONN_OUT_TIMEOUT);
/* N-DISCONNECT.ind to user */
scu_gen_encode_and_send(conn, event, NULL, OSMO_SCU_PRIM_N_DISCONNECT,
PRIM_OP_INDICATION);
@ -1112,6 +1128,7 @@ static void scoc_fsm_conn_pend_out(struct osmo_fsm_inst *fi, uint32_t event, voi
case SCOC_E_RCOC_ROUT_FAIL_IND:
case SCOC_E_RCOC_CREF_IND:
xua = data;
rate_ctr_inc2(conn->user->ctrg, SCU_CTR_CONN_OUT_CREF);
/* stop conn timer */
conn_stop_connect_timer(conn);
/* release local res + ref (implicit by going to idle) */
@ -1123,6 +1140,7 @@ static void scoc_fsm_conn_pend_out(struct osmo_fsm_inst *fi, uint32_t event, voi
break;
case SCOC_E_RCOC_RLSD_IND:
xua = data;
rate_ctr_inc2(conn->user->ctrg, SCU_CTR_CONN_OUT_RLSD);
/* RLC to SCRC */
xua_gen_encode_and_send(conn, event, NULL, SUA_CO_RELCO);
/* stop conn timer */
@ -1144,6 +1162,7 @@ static void scoc_fsm_conn_pend_out(struct osmo_fsm_inst *fi, uint32_t event, voi
break;
case SCOC_E_RCOC_CC_IND:
xua = data;
rate_ctr_inc2(conn->user->ctrg, SCU_CTR_CONN_OUT_EST);
/* stop conn timer */
conn_stop_connect_timer(conn);
/* start inactivity timers */
@ -1266,6 +1285,7 @@ static void scoc_fsm_active(struct osmo_fsm_inst *fi, uint32_t event, void *data
osmo_fsm_inst_state_chg(fi, S_IDLE, 0, 0);
break;
case SCOC_E_T_IAR_EXP:
rate_ctr_inc2(conn->user->ctrg, SCU_CTR_CONN_DISC_TIAR_EXP);
/* stop inact timers */
conn_stop_inact_timers(conn);
xua = xua_msg_alloc();

View File

@ -40,6 +40,70 @@
#include "xua_internal.h"
#include "ss7_internal.h"
static const struct rate_ctr_desc sccp_user_ctr_desc[] = {
[SCU_CTR_CLDT_OUT_COUNT] = {
"cldt.out.count", "Total number of outbound connectionless SCCP messages"
},
[SCU_CTR_CLDT_OUT_BYTES] = {
"cldt.out.bytes", "Total number of user bytes in outbound connectionless SCCP messages"
},
[SCU_CTR_CLDT_IN_COUNT] = {
"cldt.in.count", "Total number of inbound connectionless SCCP messages"
},
[SCU_CTR_CLDT_IN_BYTES] = {
"cldt.in.bytes", "Total number of user bytes in inbound connectionless SCCP messages"
},
[SCU_CTR_CONN_DISC_TIAR_EXP] = {
"conn.t_iar.expired", "Total number SCCP disconnects due to T(iar) expiration"
},
[SCU_CTR_CONN_OUT_REQ] = {
"conn.out.est.requested", "Total number of outbound SCCP connections requested"
},
[SCU_CTR_CONN_OUT_EST] = {
"conn.out.est.established", "Total number of outbound SCCP connections established"
},
[SCU_CTR_CONN_OUT_TIMEOUT] = {
"conn.out.est.timeout", "Total number of outbound SCCP connection attempts timing out"
},
[SCU_CTR_CONN_OUT_CREF] = {
"conn.out.est.refused", "Total number of outbound SCCP connection attempts refused by peer"
},
[SCU_CTR_CONN_OUT_RLSD] = {
"conn.out.est.released", "Total number of outbound SCCP connection attempts released by peer"
},
[SCU_CTR_CONN_OUT_DATA_COUNT] = {
"conn.out.data.count", "Total number of user data chunks transmitted"
},
[SCU_CTR_CONN_OUT_DATA_BYTES] = {
"conn.out.data.bytes", "Total number of user data bytes transmitted"
},
[SCU_CTR_CONN_IN_REQ] = {
"conn.in.est.requested", "Total number of inbound SCCP connections requested"
},
[SCU_CTR_CONN_IN_EST] = {
"conn.in.est.established", "Total number of inbound SCCP connections established"
},
[SCU_CTR_CONN_IN_CREF] = {
"conn.in.est.refused", "Total number of inbound SCCP connection attempts refused"
},
[SCU_CTR_CONN_IN_DATA_COUNT] = {
"conn.in.data.count", "Total number of user data chunks received"
},
[SCU_CTR_CONN_IN_DATA_BYTES] = {
"conn.in.data.bytes", "Total number of user data bytes received"
},
};
static const struct rate_ctr_group_desc sccp_user_ctrg_desc = {
.group_name_prefix = "sccp.user",
.group_description = "Counters related to one SCCP User",
.num_ctr = ARRAY_SIZE(sccp_user_ctr_desc),
.ctr_desc = sccp_user_ctr_desc,
};
/*! \brief Find a SCCP User registered for given PC+SSN or SSN only
* First search all users with a valid PC for a full PC+SSN match.
* If no such match was found, search all users with an invalid PC for an SSN-only match.
@ -113,9 +177,15 @@ sccp_user_bind_pc(struct osmo_sccp_instance *inst, const char *name,
scu->prim_cb = prim_cb;
scu->ssn = ssn;
scu->pc = pc;
scu->ctrg = rate_ctr_group_alloc(scu, &sccp_user_ctrg_desc, (pc << 8) | ssn);
if (!scu->ctrg)
goto out_free;
llist_add_tail(&scu->list, &inst->users);
return scu;
out_free:
talloc_free(scu);
return NULL;
}
/*! \brief Bind a given SCCP User to a given SSN+PC
@ -153,6 +223,7 @@ void osmo_sccp_user_unbind(struct osmo_sccp_user *scu)
osmo_ss7_pointcode_print(scu->inst->ss7, scu->pc));
/* FIXME: free/release all connections held by this user? */
llist_del(&scu->list);
rate_ctr_group_free(scu->ctrg);
talloc_free(scu);
}