WIP: rate counters for SCCP stack
TODO: * testing Change-Id: I79df56d956aaf7dee1c4f879097100e39347e44d
This commit is contained in:
parent
ba1e74c4f4
commit
0868503688
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue