SCCP: implement variable limit on Optional Data (CR,CC,CREF,RLSD)

When the Optional Data surpasses 130 bytes, it is not sent as part of
SCCP CR, CC, CREF or RLSD messages, but gets sent separately in a Data
Form 1.

Make this 130 user configurable. This is specified to be 130 bytes
exactly, but to interop with non-conforming peers, make this limit
adjustable per cs7 instance, via osmo_sccp_vty_init().

Add and test new VTY config:

	cs7 instance N
	 sccp max-optional-data (<0-999999>|standard)

Related: ITU-T Q.713 4.2 to 4.5
Related: Ia68dad973ef18513b52f5accb5264c557c7295ea osmo-ttcn3-hacks
Related: SYS#6423
Change-Id: If35697234796af8943691b2de62218e7dc93a08c
This commit is contained in:
Neels Hofmeyr 2023-04-18 21:59:41 +02:00
parent 460ba631b5
commit a0fbeeb4d2
5 changed files with 87 additions and 3 deletions

View File

@ -58,6 +58,8 @@ struct osmo_sccp_instance {
struct osmo_ss7_user ss7_user;
struct osmo_sccp_timer_val timers[OSMO_SCCP_TIMERS_COUNT];
uint32_t max_optional_data;
};
struct osmo_sccp_user {

View File

@ -676,11 +676,12 @@ static bool xua_drop_data_check_drop(const struct osmo_scu_prim *prim, unsigned
static bool xua_opt_data_cache_keep(struct sccp_connection *conn, const struct osmo_scu_prim *prim, int msg_type)
{
uint8_t *buf;
uint32_t max_optional_data = conn->inst->max_optional_data;
if (xua_drop_data_check_drop(prim, SCCP_MAX_DATA, "cache overrun"))
return false;
if (msgb_l2len(prim->oph.msg) > SCCP_MAX_OPTIONAL_DATA) {
if (msgb_l2len(prim->oph.msg) > max_optional_data) {
if (conn->opt_data_cache) {
/* Caching optional data, but there already is optional data occupying the cache: */
LOGP(DLSCCP, LOGL_ERROR, "replacing unsent %u bytes of optional data cache with %s optional data\n",
@ -703,6 +704,8 @@ static bool xua_opt_data_cache_keep(struct sccp_connection *conn, const struct o
/* Check optional Data size limit, cache if necessary, return indication whether original opt data should be sent */
static bool xua_opt_data_length_lim(struct sccp_connection *conn, const struct osmo_scu_prim *prim, int msg_type)
{
uint32_t max_optional_data = conn->inst->max_optional_data;
if (!(prim && msgb_l2(prim->oph.msg) && msgb_l2len(prim->oph.msg)))
return false;
@ -711,7 +714,7 @@ static bool xua_opt_data_length_lim(struct sccp_connection *conn, const struct o
case SUA_CO_COAK: /* §4.3 Connection confirm (CC) */
return xua_opt_data_cache_keep(conn, prim, msg_type);
case SUA_CO_COREF: /* §4.4 Connection refused (CREF) */
if (xua_drop_data_check_drop(prim, SCCP_MAX_OPTIONAL_DATA, "over ITU-T Rec. Q.713 §4.4 limit")) {
if (xua_drop_data_check_drop(prim, max_optional_data, "over ITU-T Rec. Q.713 §4.4 limit")) {
/* From the state diagrams in ITU-T Rec Q.714, there's no way to send DT1 neither before nor after CREF
* at this point, so the only option we have is to drop optional data:
* see Figure C.3 / Q.714 (sheet 2 of 6) */
@ -719,7 +722,7 @@ static bool xua_opt_data_length_lim(struct sccp_connection *conn, const struct o
}
break;
case SUA_CO_RELRE: /* §4.5 Released (RLSD) */
if (msgb_l2len(prim->oph.msg) > SCCP_MAX_OPTIONAL_DATA) {
if (msgb_l2len(prim->oph.msg) > max_optional_data) {
if (xua_drop_data_check_drop(prim, SCCP_MAX_DATA, "protocol error"))
return false;
/* There's no need to cache the optional data since the connection is still active at this point:

View File

@ -35,6 +35,7 @@
#include <osmocom/sigtran/mtp_sap.h>
#include <osmocom/sigtran/protocol/mtp.h>
#include <osmocom/sigtran/sccp_helpers.h>
#include <osmocom/sccp/sccp_types.h>
#include "sccp_internal.h"
#include "xua_internal.h"
@ -235,6 +236,7 @@ osmo_sccp_instance_create(struct osmo_ss7_instance *ss7, void *priv)
inst->ss7_user.name = "SCCP";
inst->ss7_user.prim_cb = mtp_user_prim_cb;
inst->ss7_user.priv = inst;
inst->max_optional_data = SCCP_MAX_OPTIONAL_DATA;
rc = sccp_scmg_init(inst);
if (rc < 0) {

View File

@ -37,6 +37,8 @@
#include <osmocom/sigtran/osmo_ss7.h>
#include <osmocom/sigtran/protocol/mtp.h>
#include <osmocom/sccp/sccp_types.h>
#include "xua_internal.h"
#include "sccp_internal.h"
@ -165,6 +167,36 @@ DEFUN_ATTR(sccp_timer, sccp_timer_cmd,
return CMD_SUCCESS;
}
DEFUN_ATTR(sccp_max_optional_data, sccp_max_optional_data_cmd,
"sccp max-optional-data (<0-999999>|standard)",
"Configure SCCP behavior\n"
"Adjust the upper bound for the optional data length (the payload) for CR, CC, CREF and RLSD messages."
" For any Optional Data part larger than this value in octets, send CR, CC, CREF and RLSD"
" messages without any payload, and send the data payload in a separate Data Form 1 message."
" ITU-T Q.713 sections 4.2 thru 4.5 define a limit of 130 bytes for the 'Data' parameter. This limit can be"
" adjusted here. May be useful for interop with nonstandard SCCP peers.\n"
"Set a non-standard maximum allowed number of bytes\n"
"Use the ITU-T Q.713 4.2 to 4.5 standard value of 130\n",
CMD_ATTR_IMMEDIATE)
{
struct osmo_ss7_instance *ss7 = vty->index;
int val;
if (!strcmp(argv[0], "standard"))
val = SCCP_MAX_OPTIONAL_DATA;
else
val = atoi(argv[0]);
osmo_ss7_ensure_sccp(ss7);
if (!ss7->sccp) {
vty_out(vty, "%% Error: cannot instantiate SCCP instance%s", VTY_NEWLINE);
return CMD_WARNING;
}
ss7->sccp->max_optional_data = val;
return CMD_SUCCESS;
}
static const char *osmo_sccp_timer_val_name(const struct osmo_sccp_timer_val *val)
{
static char buf[16];
@ -227,6 +259,8 @@ static void write_sccp_timers(struct vty *vty, const char *indent,
void osmo_sccp_vty_write_cs7_node(struct vty *vty, const char *indent, struct osmo_sccp_instance *inst)
{
write_sccp_timers(vty, indent, inst, false);
if (inst->max_optional_data != SCCP_MAX_OPTIONAL_DATA)
vty_out(vty, "%ssccp max-optional-data %u%s", indent, inst->max_optional_data, VTY_NEWLINE);
}
DEFUN(show_sccp_timers, show_sccp_timers_cmd,
@ -262,4 +296,5 @@ void osmo_sccp_vty_init(void)
install_lib_element_ve(&show_sccp_timers_cmd);
gen_sccp_timer_cmd_strs(&sccp_timer_cmd);
install_lib_element(L_CS7_NODE, &sccp_timer_cmd);
install_lib_element(L_CS7_NODE, &sccp_max_optional_data_cmd);
}

View File

@ -89,6 +89,7 @@ ss7_asp_vty_test(config-cs7)# list
sccp-address NAME
no sccp-address NAME
sccp-timer (conn_est|ias|iar|rel|repeat_rel|int|guard|reset|reassembly) <1-999999>
sccp max-optional-data (<0-999999>|standard)
ss7_asp_vty_test(config-cs7)# ?
...
@ -101,6 +102,7 @@ ss7_asp_vty_test(config-cs7)# ?
as Configure an Application Server
sccp-address Create/Modify an SCCP addressbook entry
sccp-timer Configure SCCP timer values, see ITU-T Q.714
sccp Configure SCCP behavior
ss7_asp_vty_test(config-cs7)# description ?
TEXT Text until the end of the line
@ -427,3 +429,43 @@ ss7_asp_vty_test(config-cs7)# sccp-timer ?
ss7_asp_vty_test(config-cs7)# sccp-timer conn_est ?
<1-999999> Timer value, in seconds
ss7_asp_vty_test(config-cs7)# sccp ?
max-optional-data Adjust the upper bound for the optional data length (the payload) for CR, CC, CREF and RLSD messages. For any Optional Data part larger than this value in octets, send CR, CC, CREF and RLSD messages without any payload, and send the data payload in a separate Data Form 1 message. ITU-T Q.713 sections 4.2 thru 4.5 define a limit of 130 bytes for the 'Data' parameter. This limit can be adjusted here. May be useful for interop with nonstandard SCCP peers.
ss7_asp_vty_test(config-cs7)# sccp max-optional-data ?
<0-999999> Set a non-standard maximum allowed number of bytes
standard Use the ITU-T Q.713 4.2 to 4.5 standard value of 130
ss7_asp_vty_test(config-cs7)# show running-config
... !sccp max-optional-data
ss7_asp_vty_test(config-cs7)# sccp max-optional-data 0
ss7_asp_vty_test(config-cs7)# show running-config
...
sccp max-optional-data 0
...
ss7_asp_vty_test(config-cs7)# sccp max-optional-data 123
ss7_asp_vty_test(config-cs7)# show running-config
...
sccp max-optional-data 123
...
ss7_asp_vty_test(config-cs7)# sccp max-optional-data 999999
ss7_asp_vty_test(config-cs7)# show running-config
...
cs7 instance 0
...
sccp max-optional-data 999999
...
cs7 instance 1
... !sccp max-optional-data
ss7_asp_vty_test(config-cs7)# sccp max-optional-data standard
ss7_asp_vty_test(config-cs7)# show running-config
... !sccp max-optional-data
ss7_asp_vty_test(config-cs7)# sccp max-optional-data 130
ss7_asp_vty_test(config-cs7)# show running-config
... !sccp max-optional-data