M3UA/SUA: Implement handling of SCON (signaling congestion)
If we receive any M3UA/SUA SNM SCON mesasages, distribute them to any other active ASP to make everyone aware of the congestion situation. This makes STP_Tests_M3UA.TC_ssnm_distribution_scon pass and hence should turn the entire osmo-stp test suite "green" Change-Id: Iac7aeba980fbbd8b58f8872a29ba10745eb0a730
This commit is contained in:
parent
7d8a674e88
commit
d51a8de505
36
src/m3ua.c
36
src/m3ua.c
|
@ -864,6 +864,40 @@ void m3ua_tx_snm_available(struct osmo_ss7_asp *asp, const uint32_t *rctx, unsig
|
|||
xua_msg_free(xua);
|
||||
}
|
||||
|
||||
/*! Transmit SSNM SCON message indicating congestion
|
||||
* \param[in] asp ASP through which to transmit message. Must be ACTIVE.
|
||||
* \param[in] rctx array of Routing Contexts in network byte order.
|
||||
* \param[in] num_rctx number of rctx
|
||||
* \param[in] aff_pc array of 'Affected Point Code' in network byte order.
|
||||
* \param[in] num_aff_pc number of aff_pc
|
||||
* \param[in] concerned_dpc optional concerned DPC (can be NULL)
|
||||
* \param[in] cong_level optional congestion level (can be NULL)
|
||||
* \param[in] info_string optional information string (can be NULL). */
|
||||
void m3ua_tx_snm_congestion(struct osmo_ss7_asp *asp, const uint32_t *rctx, unsigned int num_rctx,
|
||||
const uint32_t *aff_pc, unsigned int num_aff_pc,
|
||||
const uint32_t *concerned_dpc, const uint8_t *cong_level,
|
||||
const char *info_string)
|
||||
{
|
||||
struct xua_msg *xua = xua_msg_alloc();
|
||||
|
||||
xua->hdr = XUA_HDR(M3UA_MSGC_SNM, M3UA_SNM_SCON);
|
||||
xua->hdr.version = M3UA_VERSION;
|
||||
if (rctx)
|
||||
xua_msg_add_data(xua, M3UA_IEI_ROUTE_CTX, num_rctx * sizeof(*rctx), (const uint8_t *)rctx);
|
||||
|
||||
xua_msg_add_data(xua, M3UA_IEI_AFFECTED_PC, num_aff_pc * sizeof(*aff_pc), (const uint8_t *) aff_pc);
|
||||
|
||||
if (concerned_dpc)
|
||||
xua_msg_add_u32(xua, M3UA_IEI_CONC_DEST, *concerned_dpc & 0xffffff);
|
||||
if (cong_level)
|
||||
xua_msg_add_u32(xua, M3UA_IEI_CONG_IND, *cong_level & 0xff);
|
||||
if (info_string)
|
||||
xua_msg_add_data(xua, M3UA_IEI_INFO_STRING, strlen(info_string)+1, (const uint8_t *) info_string);
|
||||
|
||||
m3ua_tx_xua_asp(asp, xua);
|
||||
xua_msg_free(xua);
|
||||
}
|
||||
|
||||
/*! Transmit SSNM DUPU message indicating user unavailability.
|
||||
* \param[in] asp ASP through which to transmit message. Must be ACTIVE.
|
||||
* \param[in] rctx array of Routing Contexts in network byte order.
|
||||
|
@ -903,6 +937,8 @@ static int m3ua_rx_snm_asp(struct osmo_ss7_asp *asp, struct xua_msg *xua)
|
|||
xua_snm_rx_dupu(asp, as, xua);
|
||||
break;
|
||||
case M3UA_SNM_SCON:
|
||||
xua_snm_rx_scon(asp, as, xua);
|
||||
break;
|
||||
case M3UA_SNM_DRST:
|
||||
LOGPASP(asp, DLM3UA, LOGL_NOTICE, "Received unsupported M3UA SNM message type %u\n",
|
||||
xua->hdr.msg_type);
|
||||
|
|
29
src/sua.c
29
src/sua.c
|
@ -875,6 +875,35 @@ void sua_tx_snm_available(struct osmo_ss7_asp *asp, const uint32_t *rctx, unsign
|
|||
sua_tx_xua_asp(asp, xua);
|
||||
}
|
||||
|
||||
|
||||
/*! Transmit SSNM SCON message indicating congestion
|
||||
* \param[in] asp ASP through which to transmit message. Must be ACTIVE.
|
||||
* \param[in] rctx array of Routing Contexts in network byte order.
|
||||
* \param[in] num_rctx number of rctx
|
||||
* \param[in] aff_pc array of 'Affected Point Code' in network byte order.
|
||||
* \param[in] num_aff_pc number of aff_pc
|
||||
* \param[in] ssn optional SSN (can be NULL)
|
||||
* \param[in] cong_level optional congestion level (can be NULL)
|
||||
* \param[in] info_string optional information string (can be NULL). */
|
||||
void sua_tx_snm_congestion(struct osmo_ss7_asp *asp, const uint32_t *rctx, unsigned int num_rctx,
|
||||
const uint32_t *aff_pc, unsigned int num_aff_pc, const uint32_t *ssn,
|
||||
const uint8_t cong_level, const char *info_string)
|
||||
{
|
||||
struct xua_msg *xua = xua_msg_alloc();
|
||||
|
||||
xua->hdr = XUA_HDR(SUA_MSGC_SNM, SUA_SNM_SCON);
|
||||
xua->hdr.version = SUA_VERSION;
|
||||
if (rctx)
|
||||
xua_msg_add_data(xua, SUA_IEI_ROUTE_CTX, num_rctx * sizeof(*rctx), (const uint8_t *)rctx);
|
||||
xua_msg_add_data(xua, SUA_IEI_AFFECTED_PC, num_aff_pc * sizeof(*aff_pc), (const uint8_t *) aff_pc);
|
||||
if (ssn)
|
||||
xua_msg_add_u32(xua, SUA_IEI_SSN, *ssn);
|
||||
xua_msg_add_u32(xua, SUA_IEI_CONG_LEVEL, cong_level);
|
||||
if (info_string)
|
||||
xua_msg_add_data(xua, SUA_IEI_INFO_STRING, strlen(info_string)+1, (const uint8_t *) info_string);
|
||||
}
|
||||
|
||||
|
||||
/*! Transmit SSNM DUPU message indicating user unavailability.
|
||||
* \param[in] asp ASP through which to transmit message. Must be ACTIVE.
|
||||
* \param[in] rctx array of Routing Contexts in network byte order.
|
||||
|
|
|
@ -21,6 +21,9 @@ int sua_tx_xua_as(struct osmo_ss7_as *as, struct xua_msg *xua);
|
|||
void sua_tx_snm_available(struct osmo_ss7_asp *asp, const uint32_t *rctx, unsigned int num_rctx,
|
||||
const uint32_t *aff_pc, unsigned int num_aff_pc, const uint32_t *aff_ssn,
|
||||
const uint32_t *smi, const char *info_string, bool available);
|
||||
void sua_tx_snm_congestion(struct osmo_ss7_asp *asp, const uint32_t *rctx, unsigned int num_rctx,
|
||||
const uint32_t *aff_pc, unsigned int num_aff_pc, const uint32_t *ssn,
|
||||
const uint8_t cong_level, const char *info_string);
|
||||
void sua_tx_dupu(struct osmo_ss7_asp *asp, const uint32_t *rctx, unsigned int num_rctx,
|
||||
uint32_t dpc, uint16_t user, uint16_t cause, const char *info_str);
|
||||
|
||||
|
@ -30,12 +33,18 @@ int m3ua_tx_xua_as(struct osmo_ss7_as *as, struct xua_msg *xua);
|
|||
void m3ua_tx_snm_available(struct osmo_ss7_asp *asp, const uint32_t *rctx, unsigned int num_rctx,
|
||||
const uint32_t *aff_pc, unsigned int num_aff_pc,
|
||||
const char *info_string, bool available);
|
||||
void m3ua_tx_snm_congestion(struct osmo_ss7_asp *asp, const uint32_t *rctx, unsigned int num_rctx,
|
||||
const uint32_t *aff_pc, unsigned int num_aff_pc,
|
||||
const uint32_t *concerned_dpc, const uint8_t *cong_level,
|
||||
const char *info_string);
|
||||
void m3ua_tx_dupu(struct osmo_ss7_asp *asp, const uint32_t *rctx, unsigned int num_rctx,
|
||||
uint32_t dpc, uint16_t user, uint16_t cause, const char *info_str);
|
||||
|
||||
void xua_snm_rx_daud(struct osmo_ss7_asp *asp, struct xua_msg *xua);
|
||||
void xua_snm_rx_duna(struct osmo_ss7_asp *asp, struct osmo_ss7_as *as, struct xua_msg *xua);
|
||||
void xua_snm_rx_dava(struct osmo_ss7_asp *asp, struct osmo_ss7_as *as, struct xua_msg *xua);
|
||||
void xua_snm_rx_dupu(struct osmo_ss7_asp *asp, struct osmo_ss7_as *as, struct xua_msg *xua);
|
||||
void xua_snm_rx_scon(struct osmo_ss7_asp *asp, struct osmo_ss7_as *as, struct xua_msg *xua);
|
||||
int m3ua_rx_msg(struct osmo_ss7_asp *asp, struct msgb *msg);
|
||||
|
||||
struct msgb *m3ua_msgb_alloc(const char *name);
|
||||
|
|
|
@ -115,6 +115,24 @@ static void xua_tx_upu(struct osmo_ss7_asp *asp, const uint32_t *rctx, unsigned
|
|||
}
|
||||
}
|
||||
|
||||
static void xua_tx_scon(struct osmo_ss7_asp *asp, const uint32_t *rctx, unsigned int num_rctx,
|
||||
const uint32_t *aff_pc, unsigned int num_aff_pc,
|
||||
const uint32_t *concerned_dpc, const uint8_t *cong_level,
|
||||
const char *info_string)
|
||||
{
|
||||
switch (asp->cfg.proto) {
|
||||
case OSMO_SS7_ASP_PROT_M3UA:
|
||||
m3ua_tx_snm_congestion(asp, rctx, num_rctx, aff_pc, num_aff_pc,
|
||||
concerned_dpc, cong_level, info_string);
|
||||
break;
|
||||
case OSMO_SS7_ASP_PROT_SUA:
|
||||
sua_tx_snm_congestion(asp, rctx, num_rctx, aff_pc, num_aff_pc, NULL,
|
||||
cong_level ? *cong_level : 0, info_string);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* generate MTP-PAUSE / MTP-RESUME towards local SCCP users */
|
||||
static void xua_snm_pc_available_to_sccp(struct osmo_sccp_instance *sccp,
|
||||
|
@ -257,6 +275,36 @@ static void xua_snm_upu(struct osmo_ss7_as *as, uint32_t dpc, uint16_t user, uin
|
|||
}
|
||||
}
|
||||
|
||||
static void xua_snm_scon(struct osmo_ss7_as *as, const uint32_t *aff_pc, unsigned int num_aff_pc,
|
||||
const uint32_t *concerned_dpc, const uint8_t *cong_level, const char *info_string)
|
||||
{
|
||||
struct osmo_ss7_instance *s7i = as->inst;
|
||||
struct osmo_ss7_asp *asp;
|
||||
uint32_t rctx[32];
|
||||
unsigned int num_rctx;
|
||||
|
||||
/* TODO: How to translate to MTP and towards SCCP (create N-PCSTATE.ind to SCU) */
|
||||
|
||||
/* inform remote ASPs via SCON */
|
||||
llist_for_each_entry(asp, &s7i->asp_list, list) {
|
||||
/* SSNM is only permitted for ASPs in ACTIVE state */
|
||||
if (!osmo_ss7_asp_active(asp))
|
||||
continue;
|
||||
|
||||
/* only send SCON if we locally are the SG and the remote is ASP */
|
||||
if (asp->cfg.role != OSMO_SS7_ASP_ROLE_SG)
|
||||
continue;
|
||||
|
||||
num_rctx = get_all_rctx_for_asp(rctx, ARRAY_SIZE(rctx), asp, as);
|
||||
/* this can happen if the given ASP is only in the AS that reports the change,
|
||||
* which shall be excluded */
|
||||
if (num_rctx == 0)
|
||||
continue;
|
||||
|
||||
xua_tx_scon(asp, rctx, num_rctx, aff_pc, num_aff_pc, concerned_dpc, cong_level, info_string);
|
||||
}
|
||||
}
|
||||
|
||||
/* receive DAUD from ASP; pc is 'affected PC' IE with mask in network byte order! */
|
||||
void xua_snm_rx_daud(struct osmo_ss7_asp *asp, struct xua_msg *xua)
|
||||
{
|
||||
|
@ -405,3 +453,20 @@ void xua_snm_rx_dupu(struct osmo_ss7_asp *asp, struct osmo_ss7_as *as, struct xu
|
|||
|
||||
xua_snm_upu(as, aff_pc, user, cause, info_str);
|
||||
}
|
||||
|
||||
/* an incoming SUA/M3UA SCON was received from a remote SG */
|
||||
void xua_snm_rx_scon(struct osmo_ss7_asp *asp, struct osmo_ss7_as *as, struct xua_msg *xua)
|
||||
{
|
||||
struct xua_msg_part *ie_aff_pc = xua_msg_find_tag(xua, M3UA_IEI_AFFECTED_PC);
|
||||
const char *info_str = xua_msg_get_str(xua, M3UA_IEI_INFO_STRING);
|
||||
uint32_t _concerned_dpc, _cong_level;
|
||||
const uint32_t *concerned_dpc = xua_msg_get_u32p(xua, M3UA_IEI_CONC_DEST, &_concerned_dpc);
|
||||
const uint32_t *cong_level = xua_msg_get_u32p(xua, M3UA_IEI_CONG_IND, &_cong_level);
|
||||
int log_ss = osmo_ss7_asp_get_log_subsys(asp);
|
||||
|
||||
LOGPASP(asp, log_ss, LOGL_NOTICE, "RX SCON(%s) for %s level=%u\n", info_str ? info_str : "",
|
||||
format_affected_pcs_c(xua, asp->inst, ie_aff_pc), cong_level ? *cong_level : 0);
|
||||
|
||||
xua_snm_scon(as, (const uint32_t *) ie_aff_pc->dat, ie_aff_pc->len / sizeof(uint32_t),
|
||||
concerned_dpc, (const uint8_t *) cong_level, info_str);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue