Projects
osmocom:master
libosmo-sigtran
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 36
View file
commit_30999076e10f483dfb0d743eede579659b996c67.txt
Deleted
View file
commit_7781eb275da41a9b6b1ea5d8b0e802e87a8e9d53.txt
Added
View file
libosmo-sigtran_2.1.0.28.3099.dsc -> libosmo-sigtran_2.1.0.38.7781.dsc
Changed
@@ -2,7 +2,7 @@ Source: libosmo-sigtran Binary: libosmo-sigtran11, libosmo-sigtran-dbg, libosmo-sigtran-doc, libosmo-sigtran-dev, osmo-stp, osmo-stp-dbg, osmo-stp-doc Architecture: any all -Version: 2.1.0.28.3099 +Version: 2.1.0.38.7781 Maintainer: Osmocom team <openbsc@lists.osmocom.org> Homepage: https://projects.osmocom.org/projects/libosmo-sccp Standards-Version: 3.9.7 @@ -18,8 +18,8 @@ osmo-stp-dbg deb debug optional arch=any osmo-stp-doc deb doc optional arch=all Checksums-Sha1: - 2db357363fcd91c4df49593a116cfc9fdaf447fb 233644 libosmo-sigtran_2.1.0.28.3099.tar.xz + 2fdcfb22bb67d0cda9bb88082ec9191c3857d6cf 238452 libosmo-sigtran_2.1.0.38.7781.tar.xz Checksums-Sha256: - 26deaf05876e1b54e7715bf4b18042d1bc713172314a9ca6de177d7ca44adc54 233644 libosmo-sigtran_2.1.0.28.3099.tar.xz + 0baf556750a7886a5ef3d03e76a004989986a77e2682343ad021e6a351668470 238452 libosmo-sigtran_2.1.0.38.7781.tar.xz Files: - c7300279376227a80af9f1fa42360a71 233644 libosmo-sigtran_2.1.0.28.3099.tar.xz + fba348806cf7c23537c298e05eaea6a2 238452 libosmo-sigtran_2.1.0.38.7781.tar.xz
View file
libosmo-sigtran_2.1.0.28.3099.tar.xz/.tarball-version -> libosmo-sigtran_2.1.0.38.7781.tar.xz/.tarball-version
Changed
@@ -1 +1 @@ -2.1.0.28-3099 +2.1.0.38-7781
View file
libosmo-sigtran_2.1.0.28.3099.tar.xz/debian/changelog -> libosmo-sigtran_2.1.0.38.7781.tar.xz/debian/changelog
Changed
@@ -1,8 +1,8 @@ -libosmo-sigtran (2.1.0.28.3099) unstable; urgency=medium +libosmo-sigtran (2.1.0.38.7781) unstable; urgency=medium * Automatically generated changelog entry for building the Osmocom master feed - -- Osmocom OBS scripts <info@osmocom.org> Wed, 05 Mar 2025 16:52:28 +0000 + -- Osmocom OBS scripts <info@osmocom.org> Thu, 06 Mar 2025 20:17:51 +0000 libosmo-sigtran (2.1.0) unstable; urgency=medium
View file
libosmo-sigtran_2.1.0.28.3099.tar.xz/include/osmocom/sigtran/osmo_ss7.h -> libosmo-sigtran_2.1.0.38.7781.tar.xz/include/osmocom/sigtran/osmo_ss7.h
Changed
@@ -125,7 +125,8 @@ struct osmo_ss7_route; struct osmo_ss7_route * -osmo_ss7_route_lookup(struct osmo_ss7_instance *inst, uint32_t dpc); +osmo_ss7_route_lookup(struct osmo_ss7_instance *inst, uint32_t dpc) + OSMO_DEPRECATED("Use internal ss7_instance_lookup_route() instead"); const char *osmo_ss7_route_print(const struct osmo_ss7_route *rt); const char *osmo_ss7_route_name(struct osmo_ss7_route *rt, bool list_asps); struct osmo_ss7_as *
View file
libosmo-sigtran_2.1.0.28.3099.tar.xz/src/Makefile.am -> libosmo-sigtran_2.1.0.38.7781.tar.xz/src/Makefile.am
Changed
@@ -7,6 +7,7 @@ ss7_as.h \ ss7_asp.h \ ss7_asp_peer.h \ + ss7_combined_linkset.h \ ss7_instance.h \ ss7_internal.h \ ss7_link.h \ @@ -44,6 +45,7 @@ osmo_ss7_as.c \ osmo_ss7_asp.c \ osmo_ss7_asp_peer.c \ + osmo_ss7_combined_linkset.c \ osmo_ss7_hmrt.c \ osmo_ss7_instance.c \ osmo_ss7_link.c \
View file
libosmo-sigtran_2.1.0.28.3099.tar.xz/src/ipa.c -> libosmo-sigtran_2.1.0.38.7781.tar.xz/src/ipa.c
Changed
@@ -52,7 +52,7 @@ #include "ss7_internal.h" #include "xua_asp_fsm.h" -static struct msgb *ipa_to_msg(struct xua_msg *xua) +struct msgb *ipa_to_msg(struct xua_msg *xua) { struct xua_msg_part *data_ie; struct m3ua_data_hdr *data_hdr; @@ -94,19 +94,15 @@ /*! \brief Send a given xUA message via a given IPA "Application Server" * \paramin as Application Server through which to send \a xua * \paramin xua xUA message to be sent - * \return 0 on success; negative on error */ + * \return 0 on success; negative on error + * + * This function takes ownership of xua msg passed to it. + */ int ipa_tx_xua_as(struct osmo_ss7_as *as, struct xua_msg *xua) { - struct msgb *msg; OSMO_ASSERT(as->cfg.proto == OSMO_SS7_ASP_PROT_IPA); - msg = ipa_to_msg(xua); - if (!msg) { - LOGPAS(as, DLSS7, LOGL_ERROR, "Error encoding IPA Msg\n"); - return -1; - } - - return xua_as_transmit_msg(as, msg); + return xua_as_transmit_msg(as, xua); } static int ipa_rx_msg_ccm(struct osmo_ss7_asp *asp, struct msgb *msg) @@ -238,6 +234,8 @@ } rate_ctr_inc2(as->ctrg, SS7_AS_CTR_RX_MSU_TOTAL); + OSMO_ASSERT(sls <= 0xf); + rate_ctr_inc2(as->ctrg, SS7_AS_CTR_RX_MSU_SLS_0 + sls); /* pull the IPA header */ msgb_pull_to_l2(msg); @@ -296,9 +294,9 @@ /* Update xua->mtp with values from data_hdr */ m3ua_dh_to_xfer_param(&xua->mtp, &data_hdr); - /* Pass on as if we had received it from an M3UA ASP */ + /* Pass on as if we had received it from an M3UA ASP. + * xua ownership is passed here: */ rc = m3ua_hmdc_rx_from_l2(asp->inst, xua); - xua_msg_free(xua); return rc; }
View file
libosmo-sigtran_2.1.0.28.3099.tar.xz/src/m3ua.c -> libosmo-sigtran_2.1.0.38.7781.tar.xz/src/m3ua.c
Changed
@@ -486,7 +486,7 @@ ***********************************************************************/ /* Convert M3UA from xua_msg to msgb and set PPID/stream */ -static struct msgb *m3ua_to_msg(struct xua_msg *xua) +struct msgb *m3ua_to_msg(struct xua_msg *xua) { struct msgb *msg = xua_to_msg(M3UA_VERSION, xua); @@ -506,26 +506,33 @@ return msg; } -/* transmit given xua_msg via given ASP */ +/* transmit given xua_msg via given ASP + * This function takes ownership of xua msg passed to it. + */ static int m3ua_tx_xua_asp(struct osmo_ss7_asp *asp, struct xua_msg *xua) { - struct msgb *msg = m3ua_to_msg(xua); + struct msgb *msg; OSMO_ASSERT(asp->cfg.proto == OSMO_SS7_ASP_PROT_M3UA); + msg = m3ua_to_msg(xua); + xua_msg_free(xua); if (!msg) return -1; + /* msg becomes owned by osmo_ss7_asp_send here: */ return osmo_ss7_asp_send(asp, msg); } /*! \brief Send a given xUA message via a given M3UA Application Server * \paramin as Application Server through which to send \ref xua * \paramin xua xUA message to be sent - * \return 0 on success; negative on error */ + * \return 0 on success; negative on error + * + * This function takes ownership of xua msg passed to it. + */ int m3ua_tx_xua_as(struct osmo_ss7_as *as, struct xua_msg *xua) { - struct msgb *msg; int rc; OSMO_ASSERT(as->cfg.proto == OSMO_SS7_ASP_PROT_M3UA); @@ -534,17 +541,11 @@ if (as->cfg.routing_key.context) xua_msg_add_u32(xua, M3UA_IEI_ROUTE_CTX, as->cfg.routing_key.context); - msg = m3ua_to_msg(xua); - if (!msg) { - LOGPAS(as, DLM3UA, LOGL_ERROR, "Error encoding M3UA Msg\n"); - return -1; - } - /* send the msg to the AS for transmission. The AS FSM might * (depending on its state) enqueue it before transmission */ - rc = osmo_fsm_inst_dispatch(as->fi, XUA_AS_E_TRANSFER_REQ, msg); + rc = osmo_fsm_inst_dispatch(as->fi, XUA_AS_E_TRANSFER_REQ, xua); if (rc < 0) - msgb_free(msg); + xua_msg_free(xua); return rc; } @@ -570,6 +571,7 @@ return data_hdr; } +/* This function takes ownership of xua msg passed to it. */ static int m3ua_rx_xfer(struct osmo_ss7_asp *asp, struct xua_msg *xua) { struct xua_msg_part *na_ie = xua_msg_find_tag(xua, M3UA_IEI_NET_APPEAR); @@ -585,7 +587,8 @@ "%s(): unsupported message type: %s\n", __func__, get_value_string(m3ua_xfer_msgt_names, xua->hdr.msg_type)); - return M3UA_ERR_UNSUPP_MSG_TYPE; + rc = M3UA_ERR_UNSUPP_MSG_TYPE; + goto ret_free; } /* Reject unsupported Network Appearance IE. */ @@ -596,13 +599,15 @@ "Unsupported 'Network Appearance' IE '0x%08x' in message type '%s', sending 'Error'.\n", na, get_value_string(m3ua_xfer_msgt_names, xua->hdr.msg_type)); if (na_ie->len != 4) - return M3UA_ERR_PARAM_FIELD_ERR; - return M3UA_ERR_INVAL_NET_APPEAR; + rc = M3UA_ERR_PARAM_FIELD_ERR; + else + rc = M3UA_ERR_INVAL_NET_APPEAR; + goto ret_free; } rc = xua_find_as_for_asp(&as, asp, rctx_ie); if (rc) - return rc; + goto ret_free; rate_ctr_inc2(as->ctrg, SS7_AS_CTR_RX_MSU_TOTAL); @@ -617,6 +622,8 @@ "%s(): M3UA data header: opc=%u=%s dpc=%u=%s\n", __func__, xua->mtp.opc, osmo_ss7_pointcode_print(asp->inst, xua->mtp.opc), xua->mtp.dpc, osmo_ss7_pointcode_print2(asp->inst, xua->mtp.dpc)); + OSMO_ASSERT(xua->mtp.sls <= 0xf); + rate_ctr_inc2(as->ctrg, SS7_AS_CTR_RX_MSU_SLS_0 + xua->mtp.sls); if (rctx_ie) { /* remove ROUTE_CTX as in the routing case we want to add a new @@ -624,8 +631,12 @@ xua_msg_free_tag(xua, M3UA_IEI_ROUTE_CTX); } + /* xua ownership is passed here: */ return m3ua_hmdc_rx_from_l2(asp->inst, xua); - /* xua will be freed by caller m3ua_rx_msg() */ + +ret_free: + xua_msg_free(xua); + return rc; } static int m3ua_rx_mgmt_err(struct osmo_ss7_asp *asp, struct xua_msg *xua) @@ -672,16 +683,24 @@ return 0; } +/* This function takes ownership of xua msg passed to it. */ static int m3ua_rx_mgmt(struct osmo_ss7_asp *asp, struct xua_msg *xua) { + int rc; + switch (xua->hdr.msg_type) { case M3UA_MGMT_ERR: - return m3ua_rx_mgmt_err(asp, xua); + rc = m3ua_rx_mgmt_err(asp, xua); + break; case M3UA_MGMT_NTFY: - return m3ua_rx_mgmt_ntfy(asp, xua); + rc = m3ua_rx_mgmt_ntfy(asp, xua); + break; default: - return M3UA_ERR_UNSUPP_MSG_TYPE; + rc = M3UA_ERR_UNSUPP_MSG_TYPE; } + + xua_msg_free(xua); + return rc; } /* map from M3UA ASPSM/ASPTM to xua_asp_fsm event */ @@ -698,23 +717,26 @@ { M3UA_MSGC_ASPTM, M3UA_ASPTM_INACTIVE_ACK, XUA_ASP_E_ASPTM_ASPIA_ACK }, }; - +/* This function takes ownership of xua msg passed to it. */ static int m3ua_rx_asp(struct osmo_ss7_asp *asp, struct xua_msg *xua) { int event; + int rc = 0; /* map from the M3UA message class and message type to the XUA * ASP FSM event number */ event = xua_msg_event_map(xua, m3ua_aspxm_map, ARRAY_SIZE(m3ua_aspxm_map)); - if (event < 0) - return M3UA_ERR_UNSUPP_MSG_TYPE; + if (event < 0) { + rc = M3UA_ERR_UNSUPP_MSG_TYPE; + goto ret_free; + } /* deliver that event to the ASP FSM */ - if (osmo_fsm_inst_dispatch(asp->fi, event, xua) < 0) - return M3UA_ERR_UNEXPECTED_MSG; - - return 0; + rc = osmo_fsm_inst_dispatch(asp->fi, event, xua); +ret_free: + xua_msg_free(xua); + return rc; } static int m3ua_rx_snm(struct osmo_ss7_asp *asp, struct xua_msg *xua); @@ -742,9 +764,9 @@ "M3UA message\n"); if (hdr->version != M3UA_VERSION) - err = m3ua_gen_error_msg(M3UA_ERR_INVALID_VERSION, msg); + rc = M3UA_ERR_INVALID_VERSION; else - err = m3ua_gen_error_msg(M3UA_ERR_PARAM_FIELD_ERR, msg); + rc = M3UA_ERR_PARAM_FIELD_ERR; goto out; } @@ -752,7 +774,8 @@ xua_hdr_dump(xua, &xua_dialect_m3ua)); if (!xua_dialect_check_all_mand_ies(&xua_dialect_m3ua, xua)) { - err = m3ua_gen_error_msg(M3UA_ERR_MISSING_PARAM, msg); + rc = M3UA_ERR_MISSING_PARAM; + xua_msg_free(xua); goto out; } @@ -764,7 +787,8 @@ /* The DATA message MUST NOT be sent on stream 0. */ if (msgb_sctp_stream(msg) == 0) { rc = M3UA_ERR_INVAL_STREAM_ID; - break; + xua_msg_free(xua); + goto out; } rc = m3ua_rx_xfer(asp, xua); break; @@ -784,21 +808,16 @@ default: LOGPASP(asp, DLM3UA, LOGL_NOTICE, "Received unknown M3UA " "Message Class %u\n", xua->hdr.msg_class); - err = m3ua_gen_error_msg(M3UA_ERR_UNSUPP_MSG_CLASS, msg); - break; + rc = M3UA_ERR_UNSUPP_MSG_CLASS; + xua_msg_free(xua); + goto out; } +out: if (rc > 0) err = m3ua_gen_error_msg(rc, msg); - -out: - if (err) { + if (err) m3ua_tx_xua_asp(asp, err); - xua_msg_free(err); - } - - xua_msg_free(xua); - return rc; } @@ -898,7 +917,6 @@ xua = m3ua_encode_duna(rctx, num_rctx, aff_pc, num_aff_pc, info_string); m3ua_tx_xua_asp(asp, xua); - xua_msg_free(xua); } /*! Transmit SSNM SCON message indicating congestion @@ -932,7 +950,6 @@ 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. @@ -948,10 +965,10 @@ { struct xua_msg *xua = m3ua_encode_dupu(rctx, num_rctx, dpc, user, cause, info_str); m3ua_tx_xua_asp(asp, xua); - xua_msg_free(xua); } -/* received SNM message on ASP side */ +/* received SNM message on ASP side + * This function takes ownership of xua msg passed to it. */ static int m3ua_rx_snm_asp(struct osmo_ss7_asp *asp, struct xua_msg *xua) { struct osmo_ss7_as *as = NULL; @@ -960,7 +977,7 @@ rc = xua_find_as_for_asp(&as, asp, rctx_ie); if (rc) - return rc; + goto ret_free; /* report those up the stack so both other ASPs and local SCCP users can be notified */ switch (xua->hdr.msg_type) { @@ -990,14 +1007,16 @@ xua_snm_rx_daud(asp, xua); } else { LOGPASP(asp, DLM3UA, LOGL_ERROR, "DAUD not permitted in ASP role\n"); - return M3UA_ERR_UNSUPP_MSG_TYPE; + rc = M3UA_ERR_UNSUPP_MSG_TYPE; } break; default: - return M3UA_ERR_UNSUPP_MSG_TYPE; + rc = M3UA_ERR_UNSUPP_MSG_TYPE; } - return 0; +ret_free: + xua_msg_free(xua); + return rc; } /* received SNM message on SG side */
View file
libosmo-sigtran_2.1.0.28.3099.tar.xz/src/osmo_ss7_as.c -> libosmo-sigtran_2.1.0.38.7781.tar.xz/src/osmo_ss7_as.c
Changed
@@ -33,6 +33,7 @@ #include <osmocom/sigtran/osmo_ss7.h> #include <osmocom/sigtran/protocol/m3ua.h> +#include <osmocom/sigtran/mtp_sap.h> #include "ss7_as.h" #include "ss7_asp.h" @@ -54,9 +55,43 @@ { 0, NULL } }; +#define SS7_AS_CTR_RX_MSU_SLS_STR "Number of MSU received on SLS " +#define SS7_AS_CTR_TX_MSU_SLS_STR "Number of MSU transmitted on SLS " static const struct rate_ctr_desc ss7_as_rcd = { - SS7_AS_CTR_RX_MSU_TOTAL = { "rx:msu:total", "Total number of MSU received" }, - SS7_AS_CTR_TX_MSU_TOTAL = { "tx:msu:total", "Total number of MSU transmitted" }, + SS7_AS_CTR_RX_MSU_TOTAL = { "rx:msu:total", "Total number of MSU received" }, + SS7_AS_CTR_RX_MSU_SLS_0 = { "rx:msu:sls:0", SS7_AS_CTR_RX_MSU_SLS_STR "0" }, + SS7_AS_CTR_RX_MSU_SLS_1 = { "rx:msu:sls:1", SS7_AS_CTR_RX_MSU_SLS_STR "1" }, + SS7_AS_CTR_RX_MSU_SLS_2 = { "rx:msu:sls:2", SS7_AS_CTR_RX_MSU_SLS_STR "2" }, + SS7_AS_CTR_RX_MSU_SLS_3 = { "rx:msu:sls:3", SS7_AS_CTR_RX_MSU_SLS_STR "3" }, + SS7_AS_CTR_RX_MSU_SLS_4 = { "rx:msu:sls:4", SS7_AS_CTR_RX_MSU_SLS_STR "4" }, + SS7_AS_CTR_RX_MSU_SLS_5 = { "rx:msu:sls:5", SS7_AS_CTR_RX_MSU_SLS_STR "5" }, + SS7_AS_CTR_RX_MSU_SLS_6 = { "rx:msu:sls:6", SS7_AS_CTR_RX_MSU_SLS_STR "6" }, + SS7_AS_CTR_RX_MSU_SLS_7 = { "rx:msu:sls:7", SS7_AS_CTR_RX_MSU_SLS_STR "7" }, + SS7_AS_CTR_RX_MSU_SLS_8 = { "rx:msu:sls:8", SS7_AS_CTR_RX_MSU_SLS_STR "8" }, + SS7_AS_CTR_RX_MSU_SLS_9 = { "rx:msu:sls:9", SS7_AS_CTR_RX_MSU_SLS_STR "9" }, + SS7_AS_CTR_RX_MSU_SLS_10 = { "rx:msu:sls:10", SS7_AS_CTR_RX_MSU_SLS_STR "10" }, + SS7_AS_CTR_RX_MSU_SLS_11 = { "rx:msu:sls:11", SS7_AS_CTR_RX_MSU_SLS_STR "11" }, + SS7_AS_CTR_RX_MSU_SLS_12 = { "rx:msu:sls:12", SS7_AS_CTR_RX_MSU_SLS_STR "12" }, + SS7_AS_CTR_RX_MSU_SLS_13 = { "rx:msu:sls:13", SS7_AS_CTR_RX_MSU_SLS_STR "13" }, + SS7_AS_CTR_RX_MSU_SLS_14 = { "rx:msu:sls:14", SS7_AS_CTR_RX_MSU_SLS_STR "14" }, + SS7_AS_CTR_RX_MSU_SLS_15 = { "rx:msu:sls:15", SS7_AS_CTR_RX_MSU_SLS_STR "15" }, + SS7_AS_CTR_TX_MSU_TOTAL = { "tx:msu:total", "Total number of MSU transmitted" }, + SS7_AS_CTR_TX_MSU_SLS_0 = { "tx:msu:sls:0", SS7_AS_CTR_TX_MSU_SLS_STR "0" }, + SS7_AS_CTR_TX_MSU_SLS_1 = { "tx:msu:sls:1", SS7_AS_CTR_TX_MSU_SLS_STR "1" }, + SS7_AS_CTR_TX_MSU_SLS_2 = { "tx:msu:sls:2", SS7_AS_CTR_TX_MSU_SLS_STR "2" }, + SS7_AS_CTR_TX_MSU_SLS_3 = { "tx:msu:sls:3", SS7_AS_CTR_TX_MSU_SLS_STR "3" }, + SS7_AS_CTR_TX_MSU_SLS_4 = { "tx:msu:sls:4", SS7_AS_CTR_TX_MSU_SLS_STR "4" }, + SS7_AS_CTR_TX_MSU_SLS_5 = { "tx:msu:sls:5", SS7_AS_CTR_TX_MSU_SLS_STR "5" }, + SS7_AS_CTR_TX_MSU_SLS_6 = { "tx:msu:sls:6", SS7_AS_CTR_TX_MSU_SLS_STR "6" }, + SS7_AS_CTR_TX_MSU_SLS_7 = { "tx:msu:sls:7", SS7_AS_CTR_TX_MSU_SLS_STR "7" }, + SS7_AS_CTR_TX_MSU_SLS_8 = { "tx:msu:sls:8", SS7_AS_CTR_TX_MSU_SLS_STR "8" }, + SS7_AS_CTR_TX_MSU_SLS_9 = { "tx:msu:sls:9", SS7_AS_CTR_TX_MSU_SLS_STR "9" }, + SS7_AS_CTR_TX_MSU_SLS_10 = { "tx:msu:sls:10", SS7_AS_CTR_TX_MSU_SLS_STR "10" }, + SS7_AS_CTR_TX_MSU_SLS_11 = { "tx:msu:sls:11", SS7_AS_CTR_TX_MSU_SLS_STR "11" }, + SS7_AS_CTR_TX_MSU_SLS_12 = { "tx:msu:sls:12", SS7_AS_CTR_TX_MSU_SLS_STR "12" }, + SS7_AS_CTR_TX_MSU_SLS_13 = { "tx:msu:sls:13", SS7_AS_CTR_TX_MSU_SLS_STR "13" }, + SS7_AS_CTR_TX_MSU_SLS_14 = { "tx:msu:sls:14", SS7_AS_CTR_TX_MSU_SLS_STR "14" }, + SS7_AS_CTR_TX_MSU_SLS_15 = { "tx:msu:sls:15", SS7_AS_CTR_TX_MSU_SLS_STR "15" }, }; static const struct rate_ctr_group_desc ss7_as_rcgd = { @@ -164,6 +199,14 @@ LOGPAS(as, DLSS7, LOGL_INFO, "Removing ASP %s from AS\n", asp->cfg.name); + /* Remove route from AS-eSLS table: */ + for (unsigned int i = 0; i < ARRAY_SIZE(as->aesls_table); i++) { + if (as->aesls_tablei.normal_asp == asp) + as->aesls_tablei.normal_asp = NULL; + if (as->aesls_tablei.alt_asp == asp) + as->aesls_tablei.alt_asp = NULL; + } + for (i = 0; i < ARRAY_SIZE(as->cfg.asps); i++) { if (as->cfg.aspsi == asp) { as->cfg.aspsi = NULL; @@ -280,6 +323,106 @@ return asp; } +static as_ext_sls_t osmo_ss7_instance_calc_itu_as_ext_sls(const struct osmo_ss7_as *as, uint32_t opc, uint8_t sls) +{ + uint16_t opc12; + uint8_t opc3; + as_ext_sls_t as_ext_sls; + + if (as->cfg.loadshare.opc_sls) { + /* Take 12 bits from OPC according to config: */ + opc12 = (uint16_t)((opc >> as->cfg.loadshare.opc_shift) & 0x3fff); + + /* Derivate 3-bit value from 12-bit value: */ + opc3 = ((opc12 >> 9) & 0x07) ^ + ((opc12 >> 6) & 0x07) ^ + ((opc12 >> 3) & 0x07) ^ + (opc12 & 0x07); + opc3 &= 0x07; + + /* Generate 7 bit AS-extended-SLS: 3-bit OPC + 4 bit SLS: */ + as_ext_sls = (opc3 << 4) | ((sls) & 0x0f); + OSMO_ASSERT(as_ext_sls < NUM_AS_EXT_SLS); + } else { + as_ext_sls = sls; + } + + /* Pick extended-SLS bits according to config: */ + as_ext_sls = as_ext_sls >> as->cfg.loadshare.sls_shift; + return as_ext_sls; +} + +/* ITU Q.704 4.2.1: "current signalling link". Pick available already selected ASP */ +static struct osmo_ss7_asp *current_asp(const struct osmo_ss7_as *as, const struct osmo_ss7_as_esls_entry *aeslse) +{ + if (aeslse->normal_asp && osmo_ss7_asp_active(aeslse->normal_asp)) + return aeslse->normal_asp; + if (aeslse->alt_asp && osmo_ss7_asp_active(aeslse->alt_asp)) + return aeslse->alt_asp; + return NULL; +} + +static struct osmo_ss7_asp *ss7_as_select_asp_loadshare(struct osmo_ss7_as *as, const struct osmo_mtp_transfer_param *mtp) +{ + as_ext_sls_t as_ext_sls; + struct osmo_ss7_asp *asp; + + as_ext_sls = osmo_ss7_instance_calc_itu_as_ext_sls(as, mtp->opc, mtp->sls); + struct osmo_ss7_as_esls_entry *aeslse = &as->aesls_tableas_ext_sls; + + /* First check if we have a cached route for this ESLS */ + asp = current_asp(as, aeslse); + if (asp) { + if (asp == aeslse->normal_asp) { + /* We can transmit over normal ASP. + * Clean up alternative ASP since it's not needed anymore */ + if (aeslse->alt_asp) { + LOGPAS(as, DLSS7, LOGL_NOTICE, "Tx Loadshare: OPC=%u=%s,SLS=%u -> eSLS=%u: " + "Normal ASP '%s' became available, drop use of Alternative ASP '%s'\n", + mtp->opc, osmo_ss7_pointcode_print(as->inst, mtp->opc), + mtp->sls, as_ext_sls, asp->cfg.name, aeslse->alt_asp->cfg.name); + aeslse->alt_asp = NULL; + } + LOGPAS(as, DLSS7, LOGL_DEBUG, "Tx Loadshare: OPC=%u=%s,SLS=%u -> eSLS=%u: use Normal ASP '%s'\n", + mtp->opc, osmo_ss7_pointcode_print(as->inst, mtp->opc), + mtp->sls, as_ext_sls, asp->cfg.name); + return asp; + } + /* We can transmit over alternative ASP: */ + LOGPAS(as, DLSS7, LOGL_INFO, "Tx Loadshare: OPC=%u=%s,SLS=%u -> eSLS=%u: use Alternative ASP '%s'\n", + mtp->opc, osmo_ss7_pointcode_print(as->inst, mtp->opc), + mtp->sls, as_ext_sls, asp->cfg.name); + return asp; + } + + /* No current ASP available, try to find a new current ASP: */ + + /* No normal route selected yet: */ + if (!aeslse->normal_asp) { + asp = ss7_as_select_asp_roundrobin(as); + /* Either a normal route was selected or none found: */ + aeslse->normal_asp = asp; + if (asp) + LOGPAS(as, DLSS7, LOGL_DEBUG, "Tx Loadshare: OPC=%u=%s,SLS=%u -> eSLS=%u: " + "picked Normal ASP '%s' round-robin style\n", + mtp->opc, osmo_ss7_pointcode_print(as->inst, mtp->opc), + mtp->sls, as_ext_sls, asp->cfg.name); + return asp; + } + + /* Normal ASP unavailable and no alternative ASP (or unavailable too). + * start ITU Q.704 section 7 "forced rerouting" procedure: */ + asp = ss7_as_select_asp_roundrobin(as); + if (asp) { + aeslse->alt_asp = asp; + LOGPAS(as, DLSS7, LOGL_NOTICE, "Tx Loadshare: OPC=%u=%s,SLS=%u -> eSLS=%u: " + "Normal ASP '%s' unavailable, picked Alternative ASP '%s' round-robin style\n", + mtp->opc, osmo_ss7_pointcode_print(as->inst, mtp->opc), + mtp->sls, as_ext_sls, aeslse->normal_asp->cfg.name, asp->cfg.name); + } + return asp; +} + /* returns NULL if multiple ASPs would need to be selected. */ static struct osmo_ss7_asp *ss7_as_select_asp_broadcast(struct osmo_ss7_as *as) { @@ -304,18 +447,55 @@ * This function returns NULL too if multiple ASPs would be selected, ie. AS is * configured in broadcast mode and more than one ASP is configured. */ +struct osmo_ss7_asp *ss7_as_select_asp(struct osmo_ss7_as *as, const struct osmo_mtp_transfer_param *mtp) +{ + struct osmo_ss7_asp *asp = NULL; + + switch (as->cfg.mode) { + case OSMO_SS7_AS_TMOD_OVERRIDE: + asp = ss7_as_select_asp_override(as); + break; + case OSMO_SS7_AS_TMOD_LOADSHARE: + asp = ss7_as_select_asp_loadshare(as, mtp); + break; + case OSMO_SS7_AS_TMOD_ROUNDROBIN: + asp = ss7_as_select_asp_roundrobin(as); + break; + case OSMO_SS7_AS_TMOD_BCAST: + return ss7_as_select_asp_broadcast(as); + case _NUM_OSMO_SS7_ASP_TMOD: + OSMO_ASSERT(false); + } + + if (!asp) { + LOGPFSM(as->fi, "No selectable ASP in AS\n"); + return NULL; + } + return asp; +} +/*! Select an AS to transmit a message, according to AS configuration and ASP availability. + * \paramin as Application Server. + * \returns asp to send the message to, NULL if no possible asp found + * + * This function returns NULL too if multiple ASPs would be selected, ie. AS is + * configured in broadcast mode and more than one ASP is configured. + */ struct osmo_ss7_asp *osmo_ss7_as_select_asp(struct osmo_ss7_as *as) { struct osmo_ss7_asp *asp = NULL; + struct osmo_mtp_transfer_param mtp; switch (as->cfg.mode) { case OSMO_SS7_AS_TMOD_OVERRIDE: asp = ss7_as_select_asp_override(as); break; case OSMO_SS7_AS_TMOD_LOADSHARE: - /* TODO: actually use the SLS value to ensure same SLS goes - * through same ASP. Not strictly required by M3UA RFC, but - * would fit the overall principle. */ + /* We don't have OPC and SLS information in this API (which is + actually only used to route IPA msgs nowadays by osmo-bsc, so we + don't care. Use hardcoded value to provide some fallback for this scenario: */ + mtp = (struct osmo_mtp_transfer_param){0}; + asp = ss7_as_select_asp_loadshare(as, &mtp); + break; case OSMO_SS7_AS_TMOD_ROUNDROBIN: asp = ss7_as_select_asp_roundrobin(as); break;
View file
libosmo-sigtran_2.1.0.38.7781.tar.xz/src/osmo_ss7_combined_linkset.c
Added
@@ -0,0 +1,254 @@ +/* (C) 2025 by sysmocom s.f.m.c. GmbH <info@sysmocom.de> + * All Rights Reserved + * Author: Pau Espin Pedrol <pespin@sysmocom.de> + * + * SPDX-License-Identifier: GPL-2.0+ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#include <errno.h> + +#include <osmocom/core/linuxlist.h> +#include <osmocom/core/logging.h> +#include <osmocom/sigtran/osmo_ss7.h> + +#include "ss7_combined_linkset.h" +#include "ss7_route.h" +#include "ss7_route_table.h" +#include "ss7_internal.h" + +/****************************************************************************** + * SS7 Combined Linkset + * + * ITU Q.704 4.2.1: "Signalling traffic to be sent to a particular signalling + * point in the network is normally routed to one or, in the case of load + * sharing between link sets in the international network, two link sets. A load + * sharing collection of two or more link sets is called a combined link set" + * ... + * "The possible link set (combined link sets) appear in a certain priority + * order. The link set (combined link set) having the highest priority is used + * whenever it is available." + * ... + * "It is defined that the normal link set (combined link set) for traffic to the + * concerned destination. The link set (combined link set) which is in use at a + * given time is called the current link set (combined link set). The current + * link set (combined link set) consists either of the normal link set (combined + * link set) or of an alternative link set (combined link set)." + *****************************************************************************/ + +static inline struct llist_head *_ss7_llist_round_robin(struct llist_head *list, void **state) +{ + struct llist_head *e = *state; + if (!e || e->next == list) + e = list; + e = e->next; + if (e == list) + e = NULL; + *state = e; + return e; +} +#define ss7_llist_round_robin(list, state, struct_type, entry_name) \ + llist_entry(_ss7_llist_round_robin(list, state), struct_type, entry_name) + +/*! \brief Insert combined_link into its routing table + * \paramin clset Combined link to be inserted into its routing table + * \returns 0 on success, negative on error + * + * A combined link is only really used once it has been inserted into its routing table. + * + * insert the route in the ordered list of routes. The list is sorted by + * mask length, so that the more specific (longer mask) routes are + * first, while the less specific routes with shorter masks are last. + * Within the same mask length, the routes are ordered by priority. + * Hence, the first matching route in a linear iteration is the most + * specific match. + */ +static void ss7_combined_linkset_insert(struct osmo_ss7_combined_linkset *clset) +{ + struct osmo_ss7_route_table *rtbl = clset->rtable; + struct osmo_ss7_combined_linkset *it; + + llist_for_each_entry(it, &rtbl->combined_linksets, list) { + if (it->cfg.mask == clset->cfg.mask && + it->cfg.priority > clset->cfg.priority) { + /* insert before the current entry */ + llist_add(&clset->list, it->list.prev); + return; + } + if (it->cfg.mask < clset->cfg.mask) { + /* insert before the current entry */ + llist_add(&clset->list, it->list.prev); + return; + } + } + /* not added, i.e. no smaller mask length and priority found: we are the + * smallest mask and priority and thus should go last */ + llist_add_tail(&clset->list, &rtbl->combined_linksets); +} + +struct osmo_ss7_combined_linkset * +ss7_combined_linkset_alloc(struct osmo_ss7_route_table *rtbl, uint32_t pc, uint32_t mask, uint32_t prio) +{ + struct osmo_ss7_combined_linkset *clset; + + clset = talloc_zero(rtbl, struct osmo_ss7_combined_linkset); + if (!clset) + return NULL; + + clset->rtable = rtbl; + /* truncate mask to maximum. Let's avoid callers specifying arbitrary large + * masks to ensure we don't fail duplicate detection with longer mask lengths */ + clset->cfg.mask = osmo_ss7_pc_normalize(&rtbl->inst->cfg.pc_fmt, mask); + clset->cfg.pc = osmo_ss7_pc_normalize(&rtbl->inst->cfg.pc_fmt, pc); + clset->cfg.priority = prio; + INIT_LLIST_HEAD(&clset->routes); + + ss7_combined_linkset_insert(clset); + return clset; +} + +void +ss7_combined_linkset_free(struct osmo_ss7_combined_linkset *clset) +{ + if (!clset) + return; + llist_del(&clset->list); + talloc_free(clset); +} + +void ss7_combined_linkset_add_route(struct osmo_ss7_combined_linkset *clset, struct osmo_ss7_route *rt) +{ + llist_add_tail(&rt->list, &clset->routes); + clset->num_routes++; + rt->clset = clset; +} + +/* clset may end up freed as a result: */ +void ss7_combined_linkset_del_route(struct osmo_ss7_route *rt) +{ + struct osmo_ss7_combined_linkset *clset = rt->clset; + + /* Remove route from eSLS table: */ + for (unsigned int i = 0; i < ARRAY_SIZE(clset->esls_table); i++) { + if (clset->esls_tablei.normal_rt == rt) + clset->esls_tablei.normal_rt = NULL; + if (clset->esls_tablei.alt_rt == rt) + clset->esls_tablei.alt_rt = NULL; + } + + /* Update round robin state */ + if (rt == clset->last_route_roundrobin) { + ss7_llist_round_robin(&clset->routes, &clset->last_route_roundrobin, struct osmo_ss7_route, list); + /* If there's only one left, remove state: */ + if (rt == clset->last_route_roundrobin) + clset->last_route_roundrobin = NULL; + } + + llist_del(&rt->list); + rt->clset = NULL; + clset->num_routes--; + if (clset->num_routes == 0) + ss7_combined_linkset_free(clset); +} + +static ext_sls_t osmo_ss7_instance_calc_itu_ext_sls(const struct osmo_ss7_instance *inst, const struct osmo_ss7_route_label *rtlabel) +{ + /* Take 6 bits from OPC and DPC according to config: */ + uint8_t opc6 = (uint8_t)((rtlabel->opc >> inst->cfg.opc_shift) & 0x3f); + uint8_t dpc6 = (uint8_t)((rtlabel->dpc >> inst->cfg.dpc_shift) & 0x3f); + + /* Derivate 3-bit value from OPC and DPC: */ + uint8_t opc3 = ((opc6 >> 3) ^ (opc6 & 0x07)) & 0x07; + uint8_t dpc3 = ((dpc6 >> 3) ^ (dpc6 & 0x07)) & 0x07; + uint8_t opc_dpc3 = (opc3 ^ dpc3) & 0x07; + + /* Generate 7 bit extended-SLS: 3-bit OPC-DPC + 4 bit SLS: */ + uint8_t ext_sls = (opc_dpc3 << 4) | ((rtlabel->sls) & 0x0f); + OSMO_ASSERT(ext_sls < NUM_EXT_SLS); + + /* Pick extended-SLS bits according to config: */ + ext_sls = ext_sls >> inst->cfg.sls_shift; + return ext_sls; +} + +/* ITU Q.704 4.2.1: "current link set (combined link set)". Pick available already selected route */ +struct osmo_ss7_route *current_rt(const struct osmo_ss7_esls_entry *eslse) +{ + if (eslse->normal_rt && ss7_route_is_available(eslse->normal_rt)) + return eslse->normal_rt; + if (eslse->alt_rt && ss7_route_is_available(eslse->alt_rt)) + return eslse->alt_rt; + return NULL; +} + +static struct osmo_ss7_route *ss7_combined_linkset_select_route_roundrobin(struct osmo_ss7_combined_linkset *clset) +{ + struct osmo_ss7_route *rt; + struct osmo_ss7_route *rt_found = NULL; + unsigned int i = 0; + + while (i < clset->num_routes) { + i++; + rt = ss7_llist_round_robin(&clset->routes, &clset->last_route_roundrobin, struct osmo_ss7_route, list); + if (ss7_route_is_available(rt)) { + rt_found = rt; + break; + } + } + + if (!rt_found) + return NULL; + + return rt_found; +} + +struct osmo_ss7_route * +ss7_combined_linkset_lookup_route(struct osmo_ss7_combined_linkset *clset, const struct osmo_ss7_route_label *rtlabel) +{ + struct osmo_ss7_route *rt; + ext_sls_t esls = osmo_ss7_instance_calc_itu_ext_sls(clset->rtable->inst, rtlabel); + struct osmo_ss7_esls_entry *eslse = &clset->esls_tableesls; + + /* First check if we have a cached route for this ESLS */ + rt = current_rt(eslse); + if (rt) { + if (rt == eslse->normal_rt) { + /* We can transmit over normal route. + * Clean up alternative route since it's not needed anymore */ + eslse->alt_rt = NULL; + return rt; + } + /* We can transmit over alternative route: */ + return rt; + } + + /* No current route available, try to find a new current route: */ + + /* No normal route selected yet: */ + if (!eslse->normal_rt) { + rt = ss7_combined_linkset_select_route_roundrobin(clset); + /* Either a normal route was selected or none found: */ + eslse->normal_rt = rt; + return rt; + } + + /* Normal route unavailable and no alternative route (or unavailable too). + * start ITU Q.704 section 7 "forced rerouting" procedure: */ + rt = ss7_combined_linkset_select_route_roundrobin(clset); + if (rt) + eslse->alt_rt = rt; + return rt; +}
View file
libosmo-sigtran_2.1.0.28.3099.tar.xz/src/osmo_ss7_hmrt.c -> libosmo-sigtran_2.1.0.38.7781.tar.xz/src/osmo_ss7_hmrt.c
Changed
@@ -86,24 +86,35 @@ return m3ua_xfer_from_data(&data_hdr, msgb_l2(msg), msgb_l2len(msg)); } -/* delivery given XUA message to given SS7 user */ +/* delivery given XUA message to given SS7 user + * Ownership of xua_msg passed is transferred to this function. + */ static int deliver_to_mtp_user(const struct osmo_ss7_user *osu, struct xua_msg *xua) { struct osmo_mtp_prim *prim; + int rc; /* Create MTP-TRANSFER.ind and feed to user */ prim = m3ua_to_xfer_ind(xua); - if (!prim) - return -1; + if (!prim) { + rc = -1; + goto ret_free; + } prim->u.transfer = xua->mtp; - return osu->prim_cb(&prim->oph, (void *) osu->priv); + rc = osu->prim_cb(&prim->oph, (void *) osu->priv); + +ret_free: + xua_msg_free(xua); + return rc; } /* HMDC -> HMDT: Message for distribution; Figure 25/Q.704 */ /* This means it is a message we received from remote/L2, and it is to - * be routed to a local user part */ + * be routed to a local user part. + * Ownership of xua_msg passed is transferred to this function. + */ static int hmdt_message_for_distribution(struct osmo_ss7_instance *inst, struct xua_msg *xua) { struct m3ua_data_hdr *mdh; @@ -120,6 +131,7 @@ default: LOGP(DLSS7, LOGL_ERROR, "Unknown M3UA XFER Message " "Type %u\n", xua->hdr.msg_type); + xua_msg_free(xua); return -1; } break; @@ -131,6 +143,7 @@ /* Discard Message */ LOGP(DLSS7, LOGL_ERROR, "Unknown M3UA Message Class %u\n", xua->hdr.msg_class); + xua_msg_free(xua); return -1; } @@ -142,22 +155,30 @@ LOGP(DLSS7, LOGL_NOTICE, "No MTP-User for SI %u\n", service_ind); /* Discard Message */ /* FIXME: User Part Unavailable HMDT -> HMRT */ + xua_msg_free(xua); return -1; } } /* HMDC->HMRT Msg For Routing; Figure 26/Q.704 */ /* local message was receive d from L4, SRM, SLM, STM or SLTC, or - * remote message received from L2 and HMDC determined msg for routing */ + * remote message received from L2 and HMDC determined msg for routing + * Ownership of xua_msg passed is transferred to this function. + */ static int hmrt_message_for_routing(struct osmo_ss7_instance *inst, struct xua_msg *xua) { uint32_t dpc = xua->mtp.dpc; + struct osmo_ss7_route_label rtlabel = { + .opc = xua->mtp.opc, + .dpc = xua->mtp.dpc, + .sls = xua->mtp.sls, + }; struct osmo_ss7_route *rt; - /* find route for DPC */ + /* find route for OPC+DPC+SLS: */ /* FIXME: unify with gen_mtp_transfer_req_xua() */ - rt = osmo_ss7_route_lookup(inst, dpc); + rt = ss7_instance_lookup_route(inst, &rtlabel); if (rt) { /* FIXME: DPC SP restart? */ /* FIXME: DPC Congested? */ @@ -175,13 +196,9 @@ dpc, osmo_ss7_pointcode_print(inst, dpc), rt_name); } - if (osmo_ss7_as_down(as)) { - LOGP(DLSS7, LOGL_ERROR, "Unable to route HMRT message: the AS %s is down\n", - as->cfg.name); - return -ENETDOWN; - } - rate_ctr_inc2(as->ctrg, SS7_AS_CTR_TX_MSU_TOTAL); + OSMO_ASSERT(xua->mtp.sls <= 0xf); + rate_ctr_inc2(as->ctrg, SS7_AS_CTR_TX_MSU_SLS_0 + xua->mtp.sls); switch (as->cfg.proto) { case OSMO_SS7_ASP_PROT_M3UA: @@ -214,12 +231,14 @@ /* Message Received for inaccesible SP HMRT ->RTPC */ /* Discard Message */ } + xua_msg_free(xua); return -1; } /* HMDC: Received Message L2 -> L3; Figure 24/Q.704 */ /* This means a message was received from L2 and we have to decide if it - * is for the local stack (HMDT) or for routng (HMRT) */ + * is for the local stack (HMDT) or for routng (HMRT) + * Ownership of xua_msg passed is transferred to this function. */ int m3ua_hmdc_rx_from_l2(struct osmo_ss7_instance *inst, struct xua_msg *xua) { uint32_t dpc = xua->mtp.dpc; @@ -256,7 +275,6 @@ * IPv4). So we call m3ua_hmdc_rx_from_l2() just like * the MTP-TRANSFER had been received from L2. */ rc = m3ua_hmdc_rx_from_l2(inst, xua); - xua_msg_free(xua); break; default: LOGP(DLSS7, LOGL_ERROR, "Ignoring unknown primitive %u:%u\n",
View file
libosmo-sigtran_2.1.0.28.3099.tar.xz/src/osmo_ss7_instance.c -> libosmo-sigtran_2.1.0.38.7781.tar.xz/src/osmo_ss7_instance.c
Changed
@@ -202,6 +202,15 @@ return -1; } +/*! \brief Find a SS7 route for given destination point code in given SS7 */ +struct osmo_ss7_route * +ss7_instance_lookup_route(struct osmo_ss7_instance *inst, const struct osmo_ss7_route_label *rtlabel) +{ + OSMO_ASSERT(ss7_initialized); + return ss7_route_table_lookup_route(inst->rtable_system, rtlabel); +} + + /*********************************************************************** * SS7 Application Server ***********************************************************************/
View file
libosmo-sigtran_2.1.0.28.3099.tar.xz/src/osmo_ss7_route.c -> libosmo-sigtran_2.1.0.38.7781.tar.xz/src/osmo_ss7_route.c
Changed
@@ -26,6 +26,7 @@ #include <osmocom/sigtran/mtp_sap.h> #include <osmocom/sigtran/osmo_ss7.h> +#include "ss7_combined_linkset.h" #include "ss7_linkset.h" #include "ss7_as.h" #include "ss7_asp.h" @@ -132,34 +133,6 @@ return 0; } -/* insert the route in the ordered list of routes. The list is sorted by - * mask length, so that the more specific (longer mask) routes are - * first, while the less specific routes with shorter masks are last. - * Within the same mask length, the routes are ordered by priority. - * Hence, the first matching route in a linear iteration is the most - * specific match. */ -static void route_insert_sorted(struct osmo_ss7_route_table *rtbl, - struct osmo_ss7_route *cmp) -{ - struct osmo_ss7_route *rt; - - llist_for_each_entry(rt, &rtbl->routes, list) { - if (rt->cfg.mask == cmp->cfg.mask && - rt->cfg.priority > cmp->cfg.priority) { - /* insert before the current entry */ - llist_add(&cmp->list, rt->list.prev); - return; - } - if (rt->cfg.mask < cmp->cfg.mask) { - /* insert before the current entry */ - llist_add(&cmp->list, rt->list.prev); - return; - } - } - /* not added, i.e. no smaller mask length and priority found: we are the - * smallest mask and priority and thus should go last */ - llist_add_tail(&cmp->list, &rtbl->routes); -} /*! \brief Insert route into its routing table * \paramin rt Route to be inserted into its routing table @@ -170,7 +143,7 @@ int ss7_route_insert(struct osmo_ss7_route *rt) { - struct osmo_ss7_route *prev_rt; + struct osmo_ss7_combined_linkset *clset; struct osmo_ss7_route_table *rtbl = rt->rtable; if (ss7_route_inserted(rt)) { @@ -183,17 +156,24 @@ return -EINVAL; } - /* check for duplicates */ - prev_rt = ss7_route_table_find_route_by_dpc_mask(rtbl, rt->cfg.pc, rt->cfg.mask); - if (prev_rt && !strcmp(prev_rt->cfg.linkset_name, rt->cfg.linkset_name)) { - LOGSS7(rtbl->inst, LOGL_ERROR, - "Refusing to create route with existing linkset name: pc=%u=%s mask=0x%x via linkset/AS '%s'\n", - rt->cfg.pc, osmo_ss7_pointcode_print(rtbl->inst, rt->cfg.pc), - rt->cfg.mask, rt->cfg.linkset_name); - return -EADDRINUSE; + clset = ss7_route_table_find_combined_linkset(rtbl, rt->cfg.pc, rt->cfg.mask, rt->cfg.priority); + if (clset) { /* check for duplicates */ + struct osmo_ss7_route *prev_rt; + llist_for_each_entry(prev_rt, &clset->routes, list) { + if (!strcmp(prev_rt->cfg.linkset_name, rt->cfg.linkset_name)) { + LOGSS7(rtbl->inst, LOGL_ERROR, + "Refusing to create route with existing linkset name: pc=%u=%s mask=0x%x via linkset/AS '%s'\n", + rt->cfg.pc, osmo_ss7_pointcode_print(rtbl->inst, rt->cfg.pc), + rt->cfg.mask, rt->cfg.linkset_name); + return -EADDRINUSE; + } + } + } else { + clset = ss7_combined_linkset_alloc(rtbl, rt->cfg.pc, rt->cfg.mask, rt->cfg.priority); + OSMO_ASSERT(clset); } - route_insert_sorted(rtbl, rt); + ss7_combined_linkset_add_route(clset, rt); return 0; } @@ -250,7 +230,7 @@ "Destroying route: pc=%u=%s mask=0x%x via linkset/ASP '%s'\n", rt->cfg.pc, osmo_ss7_pointcode_print(inst, rt->cfg.pc), rt->cfg.mask, rt->cfg.linkset_name); - llist_del(&rt->list); + ss7_combined_linkset_del_route(rt); } talloc_free(rt); } @@ -355,12 +335,21 @@ return buf; } -/*! \brief Find a SS7 route for given destination point code in given SS7 */ +/*! \brief Find a SS7 route for given destination point code in given SS7 + * + * NOTE: DEPRECATED, use ss7_instance_lookup_route() instead + */ struct osmo_ss7_route * osmo_ss7_route_lookup(struct osmo_ss7_instance *inst, uint32_t dpc) { OSMO_ASSERT(ss7_initialized); - return ss7_route_table_find_route_by_dpc(inst->rtable_system, dpc); + struct osmo_ss7_route_label rtlb = { + .opc = 0, + .dpc = dpc, + .sls = 0, + }; + + return ss7_instance_lookup_route(inst, &rtlb); } /*! \brief Get destination AS of route @@ -373,7 +362,6 @@ return rt->dest.as; } - /* Whether route is available, ITU Q.704 */ bool ss7_route_is_available(const struct osmo_ss7_route *rt) {
View file
libosmo-sigtran_2.1.0.28.3099.tar.xz/src/osmo_ss7_route_table.c -> libosmo-sigtran_2.1.0.38.7781.tar.xz/src/osmo_ss7_route_table.c
Changed
@@ -19,15 +19,34 @@ * */ + #include <stdio.h> + #include <osmocom/core/linuxlist.h> #include <osmocom/core/logging.h> #include <osmocom/sigtran/mtp_sap.h> #include <osmocom/sigtran/osmo_ss7.h> +#include "ss7_combined_linkset.h" #include "ss7_route.h" #include "ss7_route_table.h" #include "ss7_internal.h" + +/*********************************************************************** + * SS7 Route Label + ***********************************************************************/ + +char *ss7_route_label_to_str(char *buf, size_t buf_len, const struct osmo_ss7_instance *inst, const struct osmo_ss7_route_label *rtlb) +{ + if (buf_len == 0) + return NULL; + snprintf(buf, buf_len, "OPC=%u=%s,DPC=%u=%s,SLS=%u", + rtlb->opc, osmo_ss7_pointcode_print(inst, rtlb->opc), + rtlb->dpc, osmo_ss7_pointcode_print2(inst, rtlb->dpc), + rtlb->sls); + return buf; +} + /*********************************************************************** * SS7 Route Tables ***********************************************************************/ @@ -44,7 +63,7 @@ rtbl->inst = inst; rtbl->cfg.name = talloc_strdup(rtbl, name); - INIT_LLIST_HEAD(&rtbl->routes); + INIT_LLIST_HEAD(&rtbl->combined_linksets); llist_add_tail(&rtbl->list, &inst->rtable_list); return rtbl; } @@ -77,70 +96,161 @@ ss7_route_table_destroy(struct osmo_ss7_route_table *rtbl) { llist_del(&rtbl->list); - /* routes are allocated as children of route table, will be - * automatically freed() */ + /* combined links & routes are allocated as children of route table, + * will be automatically freed() */ talloc_free(rtbl); } -/*! \brief Find a SS7 route for given destination point code in given table */ +/*! \brief Find a SS7 route for given destination point code + mask in given table. + * + * This function is used for route management procedures, not for packet routing lookup procedures! + */ struct osmo_ss7_route * -ss7_route_table_find_route_by_dpc(struct osmo_ss7_route_table *rtbl, uint32_t dpc) +ss7_route_table_find_route_by_dpc_mask(struct osmo_ss7_route_table *rtbl, uint32_t dpc, + uint32_t mask) { + struct osmo_ss7_combined_linkset *clset; struct osmo_ss7_route *rt; OSMO_ASSERT(ss7_initialized); dpc = osmo_ss7_pc_normalize(&rtbl->inst->cfg.pc_fmt, dpc); + mask = osmo_ss7_pc_normalize(&rtbl->inst->cfg.pc_fmt, mask); - /* we assume the routes are sorted by mask length, i.e. more - * specific routes first, and less specific routes with shorter + clset = ss7_route_table_find_combined_linkset_by_dpc_mask(rtbl, dpc, mask); + if (!clset) + return NULL; + rt = llist_first_entry_or_null(&clset->routes, struct osmo_ss7_route, list); + return rt; +} + +struct osmo_ss7_combined_linkset * +ss7_route_table_find_combined_linkset_by_dpc(struct osmo_ss7_route_table *rtbl, uint32_t dpc) +{ + struct osmo_ss7_combined_linkset *clset; + + OSMO_ASSERT(ss7_initialized); + + dpc = osmo_ss7_pc_normalize(&rtbl->inst->cfg.pc_fmt, dpc); + /* we assume the combined_links are sorted by mask length, i.e. more + * specific combined links first, and less specific combined links with shorter * mask later */ - llist_for_each_entry(rt, &rtbl->routes, list) { - if ((dpc & rt->cfg.mask) == rt->cfg.pc) - return rt; + llist_for_each_entry(clset, &rtbl->combined_linksets, list) { + if ((dpc & clset->cfg.mask) != clset->cfg.pc) + continue; + return clset; } return NULL; } -/*! \brief Find a SS7 route for given destination point code + mask in given table */ -struct osmo_ss7_route * -ss7_route_table_find_route_by_dpc_mask(struct osmo_ss7_route_table *rtbl, uint32_t dpc, - uint32_t mask) +struct osmo_ss7_combined_linkset * +ss7_route_table_find_combined_linkset_by_dpc_mask(struct osmo_ss7_route_table *rtbl, uint32_t dpc, uint32_t mask) { - struct osmo_ss7_route *rt; + struct osmo_ss7_combined_linkset *clset; OSMO_ASSERT(ss7_initialized); - mask = osmo_ss7_pc_normalize(&rtbl->inst->cfg.pc_fmt, mask); + dpc = osmo_ss7_pc_normalize(&rtbl->inst->cfg.pc_fmt, dpc); + /* we assume the combined_links are sorted by mask length, i.e. more + * specific combined links first, and less specific combined links with shorter + * mask later */ + llist_for_each_entry(clset, &rtbl->combined_linksets, list) { + if ((dpc & clset->cfg.mask) != clset->cfg.pc) + continue; + if (mask != clset->cfg.mask) + continue; + return clset; + } + return NULL; +} - /* we assume the routes are sorted by mask length, i.e. more +struct osmo_ss7_combined_linkset * +ss7_route_table_find_combined_linkset(struct osmo_ss7_route_table *rtbl, uint32_t dpc, uint32_t mask, uint32_t prio) +{ + struct osmo_ss7_combined_linkset *clset; + + /* we assume the combined_links are sorted by mask length, i.e. more * specific routes first, and less specific routes with shorter * mask later */ - llist_for_each_entry(rt, &rtbl->routes, list) { - if (dpc == rt->cfg.pc && mask == rt->cfg.mask) - return rt; + llist_for_each_entry(clset, &rtbl->combined_linksets, list) { + if (mask < clset->cfg.mask) + break; + if (dpc == clset->cfg.pc && mask == clset->cfg.mask) { + if (prio > clset->cfg.priority) + break; + if (prio == clset->cfg.priority) + return clset; + } } return NULL; } +struct osmo_ss7_combined_linkset * +ss7_route_table_find_or_create_combined_linkset(struct osmo_ss7_route_table *rtable, uint32_t pc, uint32_t mask, uint32_t prio) +{ + struct osmo_ss7_combined_linkset *clset; + clset = ss7_route_table_find_combined_linkset(rtable, pc, mask, prio); + if (!clset) + clset = ss7_combined_linkset_alloc(rtable, pc, mask, prio); + return clset; +} + +/* find any routes pointing to this AS and remove them */ +void ss7_route_table_del_routes_by_as(struct osmo_ss7_route_table *rtbl, struct osmo_ss7_as *as) +{ + struct osmo_ss7_combined_linkset *clset, *clset2; + + llist_for_each_entry_safe(clset, clset2, &rtbl->combined_linksets, list) { + struct osmo_ss7_route *rt; + llist_for_each_entry(rt, &clset->routes, list) { + if (rt->dest.as == as) { + ss7_route_destroy(rt); + /* clset may have been freed here. Same AS can't be twice in a combined + * linkset, so simply continue iterating in the upper loop. */ + break; + } + } + } +} + /* find any routes pointing to this linkset and remove them */ void ss7_route_table_del_routes_by_linkset(struct osmo_ss7_route_table *rtbl, struct osmo_ss7_linkset *lset) { - struct osmo_ss7_route *rt, *rt2; + struct osmo_ss7_combined_linkset *clset, *clset2; - llist_for_each_entry_safe(rt, rt2, &rtbl->routes, list) { - if (rt->dest.linkset == lset) - ss7_route_destroy(rt); + llist_for_each_entry_safe(clset, clset2, &rtbl->combined_linksets, list) { + struct osmo_ss7_route *rt; + llist_for_each_entry(rt, &clset->routes, list) { + if (rt->dest.linkset == lset) { + ss7_route_destroy(rt); + /* clset may have been freed here. Same linkset can't be twice in a combined + * linkset, so simply continue iterating in the upper loop. */ + break; + } + } } } -/* find any routes pointing to this AS and remove them */ -void ss7_route_table_del_routes_by_as(struct osmo_ss7_route_table *rtbl, struct osmo_ss7_as *as) +struct osmo_ss7_route * +ss7_route_table_lookup_route(struct osmo_ss7_route_table *rtbl, const struct osmo_ss7_route_label *rtlabel) { - struct osmo_ss7_route *rt, *rt2; - - llist_for_each_entry_safe(rt, rt2, &rtbl->routes, list) { - if (rt->dest.as == as) - ss7_route_destroy(rt); + struct osmo_ss7_combined_linkset *clset; + struct osmo_ss7_route *rt; + struct osmo_ss7_route_label rtlb = { + .opc = osmo_ss7_pc_normalize(&rtbl->inst->cfg.pc_fmt, rtlabel->opc), + .dpc = osmo_ss7_pc_normalize(&rtbl->inst->cfg.pc_fmt, rtlabel->dpc), + .sls = rtlabel->sls, + }; + /* we assume the combined_links are sorted by mask length, i.e. more + * specific combined links first, and less specific combined links with shorter + * mask later */ + llist_for_each_entry(clset, &rtbl->combined_linksets, list) { + if ((rtlb.dpc & clset->cfg.mask) != clset->cfg.pc) + continue; + rt = ss7_combined_linkset_lookup_route(clset, &rtlb); + if (!rt) + continue; + return rt; } + return NULL; }
View file
libosmo-sigtran_2.1.0.28.3099.tar.xz/src/osmo_ss7_vty.c -> libosmo-sigtran_2.1.0.38.7781.tar.xz/src/osmo_ss7_vty.c
Changed
@@ -48,6 +48,7 @@ #include "sccp_internal.h" #include "ss7_as.h" #include "ss7_asp.h" +#include "ss7_combined_linkset.h" #include "ss7_route.h" #include "ss7_route_table.h" #include "ss7_internal.h" @@ -289,6 +290,41 @@ return CMD_SUCCESS; } + +DEFUN_ATTR(cs7_opc_dpc_shift, cs7_opc_dpc_shift_cmd, + "sls-opc-dpc opc-shift <0-8> dpc-shift <0-8>", + "Shift OPC and DPC bits used during routing decision\n" + "Shift OPC bits used during routing decision\n" + "How many bits from ITU OPC field (starting from least-significant-bit) to skip (default=0). 6 bits are always used\n" + "Shift DPC bits used during routing decision\n" + "How many bits from ITU DPC field (starting from least-significant-bit) to skip (default=0). 6 bits are always used\n", + CMD_ATTR_IMMEDIATE) +{ + struct osmo_ss7_instance *inst = vty->index; + if (argc == 4) + inst->cfg.dpc_shift = atoi(argv3); + else if (argc == 3) + inst->cfg.dpc_shift = 0; + if (argc >= 2) + inst->cfg.opc_shift = atoi(argv1); + else if (argc == 1) + inst->cfg.opc_shift = 0; + + return CMD_SUCCESS; +} + +DEFUN_ATTR(cs7_sls_shift, cs7_sls_shift_cmd, + "sls-shift <0-6>", + "Shift SLS bits used during routing decision\n" + "How many bits from derivated 7-bit extended-SLS (OPC, DPC, SLS) field (starting from least-significant-bit) to skip\n", + CMD_ATTR_IMMEDIATE) +{ + struct osmo_ss7_instance *inst = vty->index; + inst->cfg.sls_shift = atoi(argv0); + + return CMD_SUCCESS; +} + static void write_one_cs7(struct vty *vty, struct osmo_ss7_instance *inst, bool show_dyn_config); static int write_all_cs7(struct vty *vty, bool show_dyn_config) @@ -487,27 +523,31 @@ static void write_one_rtable(struct vty *vty, struct osmo_ss7_route_table *rtable) { + struct osmo_ss7_combined_linkset *clset; struct osmo_ss7_route *rt; vty_out(vty, " route-table %s%s", rtable->cfg.name, VTY_NEWLINE); if (rtable->cfg.description) vty_out(vty, " description %s%s", rtable->cfg.description, VTY_NEWLINE); - llist_for_each_entry(rt, &rtable->routes, list) { - vty_out(vty, " update route %s %s linkset %s", - osmo_ss7_pointcode_print(rtable->inst, rt->cfg.pc), - osmo_ss7_pointcode_print2(rtable->inst, rt->cfg.mask), - rt->cfg.linkset_name); - if (rt->cfg.priority != OSMO_SS7_ROUTE_PRIO_DEFAULT) - vty_out(vty, " priority %u", rt->cfg.priority); - if (rt->cfg.qos_class) - vty_out(vty, " qos-class %u", rt->cfg.qos_class); - vty_out(vty, "%s", VTY_NEWLINE); + llist_for_each_entry(clset, &rtable->combined_linksets, list) { + llist_for_each_entry(rt, &clset->routes, list) { + vty_out(vty, " update route %s %s linkset %s", + osmo_ss7_pointcode_print(rtable->inst, rt->cfg.pc), + osmo_ss7_pointcode_print2(rtable->inst, rt->cfg.mask), + rt->cfg.linkset_name); + if (rt->cfg.priority != OSMO_SS7_ROUTE_PRIO_DEFAULT) + vty_out(vty, " priority %u", rt->cfg.priority); + if (rt->cfg.qos_class) + vty_out(vty, " qos-class %u", rt->cfg.qos_class); + vty_out(vty, "%s", VTY_NEWLINE); + } } } /* "filter_pc == OSMO_SS7_PC_INVALID" means "show all" */ static void vty_dump_rtable(struct vty *vty, struct osmo_ss7_route_table *rtbl, uint32_t filter_pc) { + struct osmo_ss7_combined_linkset *clset; struct osmo_ss7_route *rt; vty_out(vty, "Routing table = %s%s", rtbl->cfg.name, VTY_NEWLINE); @@ -516,23 +556,25 @@ vty_out(vty, "Destination C Q P Linkset Name Linkset Non-adj Route%s", VTY_NEWLINE); vty_out(vty, "---------------------- - - - ------------------- ------- ------- -------%s", VTY_NEWLINE); - llist_for_each_entry(rt, &rtbl->routes, list) { - if ((filter_pc != OSMO_SS7_PC_INVALID) && ((filter_pc & rt->cfg.mask) != rt->cfg.pc)) - continue; /* Skip routes not matching destination */ - - bool rt_avail = ss7_route_is_available(rt); - - vty_out(vty, "%-16s %-5s %c %c %u %-19s %-7s %-7s %-7s%s", - osmo_ss7_route_print(rt), - rt_avail ? "acces" : "INACC", - ' ', - '0' + rt->cfg.qos_class, - rt->cfg.priority, - rt->cfg.linkset_name, - rt_avail ? "avail" : "UNAVAIL", - "?", - rt_avail ? "avail" : "UNAVAIL", - VTY_NEWLINE); + llist_for_each_entry(clset, &rtbl->combined_linksets, list) { + if ((filter_pc != OSMO_SS7_PC_INVALID) && ((filter_pc & clset->cfg.mask) != clset->cfg.pc)) + continue; /* Skip combined linksets not matching destination */ + + llist_for_each_entry(rt, &clset->routes, list) { + bool rt_avail = ss7_route_is_available(rt); + + vty_out(vty, "%-16s %-5s %c %c %u %-19s %-7s %-7s %-7s%s", + osmo_ss7_route_print(rt), + rt_avail ? "acces" : "INACC", + ' ', + '0' + rt->cfg.qos_class, + rt->cfg.priority, + rt->cfg.linkset_name, + rt_avail ? "avail" : "UNAVAIL", + "?", + rt_avail ? "avail" : "UNAVAIL", + VTY_NEWLINE); + } } } @@ -577,7 +619,7 @@ bool list_asps = argc > 4; struct osmo_ss7_instance *inst; struct osmo_ss7_route *rt; - uint32_t dpc; + struct osmo_ss7_route_label rtlabel = {}; int pc; inst = osmo_ss7_instance_find(id); @@ -591,18 +633,22 @@ vty_out(vty, "Invalid point code (%s)%s", argv1, VTY_NEWLINE); return CMD_WARNING; } - dpc = pc; + rtlabel.dpc = pc; pc = osmo_ss7_pointcode_parse(inst, argv2); if (pc < 0 || !osmo_ss7_pc_is_valid((uint32_t)pc)) { vty_out(vty, "Invalid point code (%s)%s", argv2, VTY_NEWLINE); return CMD_WARNING; } + rtlabel.opc = pc; + + rtlabel.sls = atoi(argv3); - rt = osmo_ss7_route_lookup(inst, dpc); + rt = ss7_instance_lookup_route(inst, &rtlabel); if (!rt) { - vty_out(vty, "No route found for DPC %s%s", - osmo_ss7_pointcode_print(inst, dpc), VTY_NEWLINE); + char buf256; + vty_out(vty, "No route found for label '%s'%s", + ss7_route_label_to_str(buf, sizeof(buf), inst, &rtlabel), VTY_NEWLINE); return CMD_WARNING; } @@ -1987,10 +2033,9 @@ DEFUN_USRATTR(as_traf_mode, as_traf_mode_cmd, OSMO_SCCP_LIB_ATTR_RSTRT_ASP, - "traffic-mode (broadcast | loadshare | roundrobin | override)", + "traffic-mode (broadcast | roundrobin | override)", "Specifies traffic mode of operation of the ASP within the AS\n" "Broadcast to all ASP within AS\n" - "Share Load among all ASP within AS\n" "Round-Robin between all ASP within AS\n" "Override\n") { @@ -2001,6 +2046,36 @@ return CMD_SUCCESS; } +DEFUN_USRATTR(as_traf_mode_loadshare, as_traf_mode_loadshare_cmd, + OSMO_SCCP_LIB_ATTR_RSTRT_ASP, + "traffic-mode loadshare bindings sls opc-sls opc-shift <0-2>", + "Specifies traffic mode of operation of the ASP within the AS\n" + "Share Load among all ASP within AS\n" + "Configure Loadshare parameters\n" + "Configure Loadshare SLS generation parameters\n" + "Generate extended SLS with OPC information\n" + "Shift OPC bits used during routing decision\n" + "How many bits from ITU OPC field (starting from least-significant-bit) to skip (default=0). 6 bits are always used\n" + ) +{ + struct osmo_ss7_as *as = vty->index; + + as->cfg.mode = OSMO_SS7_AS_TMOD_LOADSHARE; + as->cfg.mode_set_by_vty = true; + if (argc < 3) { + as->cfg.loadshare.opc_sls = false; + as->cfg.loadshare.opc_shift = 0; + return CMD_SUCCESS; + } + as->cfg.loadshare.opc_sls = true; + if (argc < 5) { + as->cfg.loadshare.opc_shift = 0; + return CMD_SUCCESS; + } + as->cfg.loadshare.opc_shift = atoi(argv4); + return CMD_SUCCESS; +} + DEFUN_USRATTR(as_no_traf_mode, as_no_traf_mode_cmd, OSMO_SCCP_LIB_ATTR_RSTRT_ASP, "no traffic-mode", @@ -2010,6 +2085,22 @@ as->cfg.mode = 0; as->cfg.mode_set_by_vty = false; + + as->cfg.loadshare.sls_shift = 0; + as->cfg.loadshare.opc_sls = false; + as->cfg.loadshare.opc_shift = 0; + return CMD_SUCCESS; +} + +DEFUN_ATTR(as_sls_shift, as_sls_shift_cmd, + "sls-shift <0-3>", + "Shift SLS bits used during routing decision\n" + "How many bits from SLS field (starting from least-significant-bit) to skip\n", + CMD_ATTR_IMMEDIATE) +{ + struct osmo_ss7_as *as = vty->index; + as->cfg.loadshare.sls_shift = atoi(argv0); + return CMD_SUCCESS; } @@ -2228,9 +2319,21 @@ continue; vty_out(vty, " asp %s%s", asp->cfg.name, VTY_NEWLINE); } - if (as->cfg.mode_set_by_vty) - vty_out(vty, " traffic-mode %s%s", - osmo_ss7_as_traffic_mode_name(as->cfg.mode), VTY_NEWLINE); + if (as->cfg.mode_set_by_vty) { + vty_out(vty, " traffic-mode %s%s", osmo_ss7_as_traffic_mode_name(as->cfg.mode), VTY_NEWLINE); + if (as->cfg.mode == OSMO_SS7_AS_TMOD_LOADSHARE) { + if (as->cfg.loadshare.opc_sls) { + vty_out(vty, " bindings sls opc-sls"); + if (as->cfg.loadshare.opc_shift != 0) + vty_out(vty, " opc-shift %u", as->cfg.loadshare.opc_shift); + } + vty_out(vty, "%s", VTY_NEWLINE); + } + + if (as->cfg.loadshare.sls_shift != 0) + vty_out(vty, " sls-shift %u%s", as->cfg.loadshare.sls_shift, VTY_NEWLINE); + } + if (as->cfg.recovery_timeout_msec != 2000) { vty_out(vty, " recovery-timeout %u%s", as->cfg.recovery_timeout_msec, VTY_NEWLINE); @@ -2964,6 +3067,13 @@ if (inst->cfg.permit_dyn_rkm_alloc) vty_out(vty, " xua rkm routing-key-allocation dynamic-permitted%s", VTY_NEWLINE); + if (inst->cfg.opc_shift != 0 || inst->cfg.dpc_shift != 0) + vty_out(vty, " sls-opc-dpc opc-shift %u dpc-shift %u%s", + inst->cfg.opc_shift, inst->cfg.dpc_shift, VTY_NEWLINE); + + if (inst->cfg.sls_shift != 0) + vty_out(vty, " sls-shift %u%s", inst->cfg.sls_shift, VTY_NEWLINE); + /* first dump ASPs, as ASs reference them */ llist_for_each_entry(asp, &inst->asp_list, list) write_one_asp(vty, asp, show_dyn_config); @@ -3126,6 +3236,8 @@ install_lib_element(L_CS7_NODE, &cs7_pc_format_def_cmd); install_lib_element(L_CS7_NODE, &cs7_pc_delimiter_cmd); install_lib_element(L_CS7_NODE, &cs7_permit_dyn_rkm_cmd); + install_lib_element(L_CS7_NODE, &cs7_opc_dpc_shift_cmd); + install_lib_element(L_CS7_NODE, &cs7_sls_shift_cmd); install_node(&asp_node, NULL); install_lib_element_ve(&show_cs7_asp_cmd); @@ -3163,7 +3275,9 @@ install_lib_element(L_CS7_AS_NODE, &as_asp_cmd); install_lib_element(L_CS7_AS_NODE, &as_no_asp_cmd); install_lib_element(L_CS7_AS_NODE, &as_traf_mode_cmd); + install_lib_element(L_CS7_AS_NODE, &as_traf_mode_loadshare_cmd); install_lib_element(L_CS7_AS_NODE, &as_no_traf_mode_cmd); + install_lib_element(L_CS7_AS_NODE, &as_sls_shift_cmd); install_lib_element(L_CS7_AS_NODE, &as_recov_tout_cmd); install_lib_element(L_CS7_AS_NODE, &as_qos_class_cmd); install_lib_element(L_CS7_AS_NODE, &as_rout_key_cmd);
View file
libosmo-sigtran_2.1.0.28.3099.tar.xz/src/sccp_scoc.c -> libosmo-sigtran_2.1.0.38.7781.tar.xz/src/sccp_scoc.c
Changed
@@ -102,6 +102,11 @@ uint32_t sccp_class; uint32_t release_cause; /* WAIT_CONN_CONF */ + /* SLS to be used to transmit all Connection-oriented messages + * (ITU-T Q.714 1.1.2.3 Protocol class 2). + * SLS is 4 bits, as described in ITU Q.704 Figure 3 */ + uint8_t tx_co_mtp_sls; + struct msgb *opt_data_cache; /* incoming (true) or outgoing (false) */ @@ -450,6 +455,26 @@ #define INIT_TIMER(x, fn, priv) do { (x)->cb = fn; (x)->data = priv; } while (0) +/* Generate an SLS to be used for Connection-oriented messages on this SCCP connection. + * SLS is 4 bits, as described in ITU Q.704 Figure 3. + * ITU-T Q.714 1.1.2.3 Protocol class 2: + * "Messages belonging to a given signalling connection shall contain the same + * value of the SLS field to ensure sequencing as described in 1.1.2.2" + */ +static uint8_t sccp_conn_gen_tx_co_mtp_sls(const struct sccp_connection *conn) +{ + /* Implementation: Derive the SLS from conn->conn_id. */ + const uint32_t id = conn->conn_id; + uint8_t sls; + + /* First shrink it to 1 byte: */ + sls = ((id >> (3*8)) ^ (id >> (2*8)) ^ (id >> (1*8)) ^ (id)) & 0xff; + /* Now shrink it 8 -> 4 bits: */ + sls = ((sls >> 4) ^ sls) & 0x0f; + + return sls; +} + /* allocate + init a SCCP Connection with given ID */ static struct sccp_connection *conn_create_id(struct osmo_sccp_user *user, uint32_t conn_id) { @@ -472,6 +497,8 @@ INIT_TIMER(&conn->t_int, int_tmr_cb, conn); INIT_TIMER(&conn->t_rep_rel, rep_rel_tmr_cb, conn); + conn->tx_co_mtp_sls = sccp_conn_gen_tx_co_mtp_sls(conn); + /* this might change at runtime, as it is not a constant :/ */ sccp_scoc_fsm.log_subsys = DLSCCP; @@ -715,6 +742,13 @@ if (!xua) return NULL; + /* amend this with point code information; Many CO msgs + * includes neither called nor calling party address! */ + xua->mtp.dpc = conn->remote_pc; + + /* Apply SLS calculated for the connection (ITU-T Q.714 1.1.2.3). */ + xua->mtp.sls = conn->tx_co_mtp_sls; + switch (msg_type) { case SUA_CO_CORE: /* Connect Request == SCCP CR */ xua->hdr = XUA_HDR(SUA_MSGC_CO, SUA_CO_CORE); @@ -835,9 +869,6 @@ if (!xua) return -ENOMEM; - /* amend this with point code information; Many CO msgs - * includes neither called nor calling party address! */ - xua->mtp.dpc = conn->remote_pc; sccp_scrc_rx_scoc_conn_msg(conn->inst, xua); xua_msg_free(xua); return 0;
View file
libosmo-sigtran_2.1.0.28.3099.tar.xz/src/sccp_scrc.c -> libosmo-sigtran_2.1.0.38.7781.tar.xz/src/sccp_scrc.c
Changed
@@ -37,6 +37,7 @@ #include "ss7_instance.h" #include "ss7_linkset.h" #include "ss7_route.h" +#include "ss7_route_table.h" #include "xua_internal.h" @@ -120,6 +121,7 @@ const struct osmo_sccp_addr *called) { struct osmo_ss7_route *rt; + struct osmo_ss7_route_label rtlabel; /* this is a bit fishy due to the different requirements of * classic SSCP/MTP compared to various SIGTRAN stackings. @@ -144,7 +146,13 @@ return -1; } - rt = osmo_ss7_route_lookup(inst->ss7, xua->mtp.dpc); + rtlabel = (struct osmo_ss7_route_label){ + .opc = xua->mtp.opc, + .dpc = xua->mtp.dpc, + .sls = xua->mtp.sls, + }; + + rt = ss7_instance_lookup_route(inst->ss7, &rtlabel); if (!rt) { LOGP(DLSCCP, LOGL_ERROR, "MTP-TRANSFER.req from SCCP for " "DPC %u: no route!\n", xua->mtp.dpc);
View file
libosmo-sigtran_2.1.0.28.3099.tar.xz/src/ss7_as.h -> libosmo-sigtran_2.1.0.38.7781.tar.xz/src/ss7_as.h
Changed
@@ -17,6 +17,7 @@ struct osmo_ss7_instance; struct osmo_ss7_asp; +struct osmo_mtp_transfer_param; enum osmo_ss7_as_patch_sccp_mode { OSMO_SS7_PATCH_NONE, /* no patching of SCCP */ @@ -25,7 +26,48 @@ enum ss7_as_ctr { SS7_AS_CTR_RX_MSU_TOTAL, + SS7_AS_CTR_RX_MSU_SLS_0, + SS7_AS_CTR_RX_MSU_SLS_1, + SS7_AS_CTR_RX_MSU_SLS_2, + SS7_AS_CTR_RX_MSU_SLS_3, + SS7_AS_CTR_RX_MSU_SLS_4, + SS7_AS_CTR_RX_MSU_SLS_5, + SS7_AS_CTR_RX_MSU_SLS_6, + SS7_AS_CTR_RX_MSU_SLS_7, + SS7_AS_CTR_RX_MSU_SLS_8, + SS7_AS_CTR_RX_MSU_SLS_9, + SS7_AS_CTR_RX_MSU_SLS_10, + SS7_AS_CTR_RX_MSU_SLS_11, + SS7_AS_CTR_RX_MSU_SLS_12, + SS7_AS_CTR_RX_MSU_SLS_13, + SS7_AS_CTR_RX_MSU_SLS_14, + SS7_AS_CTR_RX_MSU_SLS_15, SS7_AS_CTR_TX_MSU_TOTAL, + SS7_AS_CTR_TX_MSU_SLS_0, + SS7_AS_CTR_TX_MSU_SLS_1, + SS7_AS_CTR_TX_MSU_SLS_2, + SS7_AS_CTR_TX_MSU_SLS_3, + SS7_AS_CTR_TX_MSU_SLS_4, + SS7_AS_CTR_TX_MSU_SLS_5, + SS7_AS_CTR_TX_MSU_SLS_6, + SS7_AS_CTR_TX_MSU_SLS_7, + SS7_AS_CTR_TX_MSU_SLS_8, + SS7_AS_CTR_TX_MSU_SLS_9, + SS7_AS_CTR_TX_MSU_SLS_10, + SS7_AS_CTR_TX_MSU_SLS_11, + SS7_AS_CTR_TX_MSU_SLS_12, + SS7_AS_CTR_TX_MSU_SLS_13, + SS7_AS_CTR_TX_MSU_SLS_14, + SS7_AS_CTR_TX_MSU_SLS_15, +}; + +#define NUM_AS_EXT_SLS 128 +typedef uint8_t as_ext_sls_t; /* range: 0-127, 7 bit */ +struct osmo_ss7_as_esls_entry { + /* ITU Q.704 4.2.1: "normal signallink link" */ + struct osmo_ss7_asp *normal_asp; + /* ITU Q.704 4.2.1: "alternative signallink link" */ + struct osmo_ss7_asp *alt_asp; }; struct osmo_ss7_as { @@ -45,6 +87,9 @@ /*! Rate Counter Group */ struct rate_ctr_group *ctrg; + /* ASP loadshare: */ + struct osmo_ss7_as_esls_entry aesls_tableNUM_AS_EXT_SLS; + struct { char *name; char *description; @@ -64,9 +109,24 @@ struct osmo_ss7_asp *asps16; uint8_t last_asp_idx_sent; /* used for load-sharing traffic mode (round robin implementation) */ + + struct { + /* How many bits from ITU SLS field (starting from least-significant-bit) + * to skip for routing decisions. + * range 0-3, defaults to 0, which means take all 4 bits. */ + uint8_t sls_shift; + /* Whether to generate a extended-SLS with OPC information, see opc_shift below. */ + bool opc_sls; + /* How many bits from ITU OPC field (starting from least-significant-bit) + * to skip for routing decisions (always takes 12 bits). + * range 0-2, defaults to 0, which means take least significant 12 bits. */ + uint8_t opc_shift; + } loadshare; } cfg; }; +struct osmo_ss7_asp *ss7_as_select_asp(struct osmo_ss7_as *as, const struct osmo_mtp_transfer_param *mtp); + unsigned int osmo_ss7_as_count_asp(const struct osmo_ss7_as *as); int ss7_as_add_asp(struct osmo_ss7_as *as, struct osmo_ss7_asp *asp);
View file
libosmo-sigtran_2.1.0.38.7781.tar.xz/src/ss7_combined_linkset.h
Added
@@ -0,0 +1,58 @@ +#pragma once + +#include <stdint.h> +#include <osmocom/core/linuxlist.h> + +/*********************************************************************** + * SS7 Combined Linkset + * Set of routes with same destination and priority. + ***********************************************************************/ + +struct osmo_ss7_instance; +struct osmo_ss7_link; +struct osmo_ss7_route_label; + +#define NUM_EXT_SLS 128 +typedef uint8_t ext_sls_t; /* range: 0-127, 7 bit */ + +struct osmo_ss7_esls_entry { + /* ITU Q.704 4.2.1: "normal link set (combined link set)" */ + struct osmo_ss7_route *normal_rt; + /* ITU Q.704 4.2.1: "alternative link set (combined link set)" */ + struct osmo_ss7_route *alt_rt; +}; + +struct osmo_ss7_combined_linkset { + /*! member in \ref osmo_ss7_route_table.combined_linksets */ + struct llist_head list; + + /*! \ref osmo_ss7_route_table to which we belong */ + struct osmo_ss7_route_table *rtable; + struct osmo_ss7_esls_entry esls_tableNUM_EXT_SLS; + + /*! list of \ref osmo_ss7_route */ + struct llist_head routes; + unsigned int num_routes; + void *last_route_roundrobin; + + struct { + uint32_t pc; + uint32_t mask; + /*! lower priority is higher */ + uint32_t priority; + } cfg; +}; + +struct osmo_ss7_combined_linkset * +ss7_combined_linkset_alloc(struct osmo_ss7_route_table *rtbl, uint32_t pc, uint32_t mask, uint32_t prio); +void +ss7_combined_linkset_free(struct osmo_ss7_combined_linkset *clset); +struct osmo_ss7_linkset * +ss7_combined_linkset_find_or_create(struct osmo_ss7_route_table *rtbl, uint32_t pc, uint32_t mask, uint32_t prio); + +void +ss7_combined_linkset_add_route(struct osmo_ss7_combined_linkset *clset, struct osmo_ss7_route *rt); +void +ss7_combined_linkset_del_route(struct osmo_ss7_route *rt); +struct osmo_ss7_route * +ss7_combined_linkset_lookup_route(struct osmo_ss7_combined_linkset *clset, const struct osmo_ss7_route_label *rtlabel);
View file
libosmo-sigtran_2.1.0.28.3099.tar.xz/src/ss7_instance.h -> libosmo-sigtran_2.1.0.38.7781.tar.xz/src/ss7_instance.h
Changed
@@ -10,6 +10,7 @@ struct osmo_ss7_user; struct osmo_ss7_route_table; +struct osmo_ss7_route_label; struct osmo_sccp_instance; struct osmo_ss7_pc_fmt { @@ -49,6 +50,15 @@ bool permit_dyn_rkm_alloc; struct llist_head sccp_address_book; uint32_t secondary_pc; + /* How many bits from ITU OPC/DPC field (starting from least-significant-bit) + * to skip for routing decisions (always takes 6 bits). + * range 0-8, defaults to 0, which means take least significant 6 bits. */ + uint8_t opc_shift; + uint8_t dpc_shift; + /* How many bits from ITU SLS field (starting from least-significant-bit) + * to skip for routing decisions. + * range 0-3, defaults to 0, which means take all 4 bits. */ + uint8_t sls_shift; } cfg; }; @@ -56,6 +66,8 @@ ss7_instance_alloc(void *ctx, uint32_t id); uint32_t ss7_find_free_l_rk_id(struct osmo_ss7_instance *inst); +struct osmo_ss7_route * +ss7_instance_lookup_route(struct osmo_ss7_instance *inst, const struct osmo_ss7_route_label *rtlabel); #define _LOGSS7(inst, subsys, level, fmt, args ...) \ LOGP(subsys, level, "%u: " fmt, inst ? (inst)->cfg.id : 0, ## args)
View file
libosmo-sigtran_2.1.0.28.3099.tar.xz/src/ss7_route.h -> libosmo-sigtran_2.1.0.38.7781.tar.xz/src/ss7_route.h
Changed
@@ -15,10 +15,12 @@ #define OSMO_SS7_ROUTE_PRIO_DEFAULT 5 struct osmo_ss7_route { - /*! member in \ref osmo_ss7_route_table.routes */ + /*! member in \ref osmo_ss7_combined_linkset.routes */ struct llist_head list; /*! \ref osmo_ss7_route_table to which we belong */ struct osmo_ss7_route_table *rtable; + /* Combined linkset this route is part of */ + struct osmo_ss7_combined_linkset *clset; struct { /*! pointer to linkset (destination) of route */
View file
libosmo-sigtran_2.1.0.28.3099.tar.xz/src/ss7_route_table.h -> libosmo-sigtran_2.1.0.38.7781.tar.xz/src/ss7_route_table.h
Changed
@@ -1,6 +1,7 @@ #pragma once #include <stdint.h> +#include <unistd.h> #include <osmocom/core/linuxlist.h> /*********************************************************************** @@ -9,13 +10,20 @@ struct osmo_ss7_instance; +struct osmo_ss7_route_label { + uint32_t opc; + uint32_t dpc; + uint8_t sls; +}; +char *ss7_route_label_to_str(char *buf, size_t buf_len, const struct osmo_ss7_instance *inst, const struct osmo_ss7_route_label *rtlb); + struct osmo_ss7_route_table { /*! member in list of routing tables */ struct llist_head list; /*! \ref osmo_ss7_instance to which we belong */ struct osmo_ss7_instance *inst; - /*! list of \ref osmo_ss7_route */ - struct llist_head routes; + /*! list of \ref osmo_ss7_combined_linksets*/ + struct llist_head combined_linksets; struct { char *name; @@ -30,10 +38,21 @@ void ss7_route_table_destroy(struct osmo_ss7_route_table *rtbl); struct osmo_ss7_route * -ss7_route_table_find_route_by_dpc(struct osmo_ss7_route_table *rtbl, uint32_t dpc); -struct osmo_ss7_route * ss7_route_table_find_route_by_dpc_mask(struct osmo_ss7_route_table *rtbl, uint32_t dpc, uint32_t mask); +struct osmo_ss7_route * +ss7_route_table_lookup_route(struct osmo_ss7_route_table *rtbl, const struct osmo_ss7_route_label *rtlabel); + +struct osmo_ss7_combined_linkset * +ss7_route_table_find_combined_linkset(struct osmo_ss7_route_table *rtbl, uint32_t dpc, uint32_t mask, uint32_t prio); +struct osmo_ss7_combined_linkset * +ss7_route_table_find_or_create_combined_linkset(struct osmo_ss7_route_table *rtbl, uint32_t pc, uint32_t mask, uint32_t prio); +struct osmo_ss7_combined_linkset * +ss7_route_table_find_combined_linkset_by_dpc(struct osmo_ss7_route_table *rtbl, uint32_t dpc); +struct osmo_ss7_combined_linkset * +ss7_route_table_find_combined_linkset_by_dpc_mask(struct osmo_ss7_route_table *rtbl, uint32_t dpc, uint32_t mask); +struct osmo_ss7_combined_linkset * +ss7_route_table_find_combined_linkset(struct osmo_ss7_route_table *rtbl, uint32_t dpc, uint32_t mask, uint32_t prio); void ss7_route_table_del_routes_by_as(struct osmo_ss7_route_table *rtbl, struct osmo_ss7_as *as); void ss7_route_table_del_routes_by_linkset(struct osmo_ss7_route_table *rtbl, struct osmo_ss7_linkset *lset);
View file
libosmo-sigtran_2.1.0.28.3099.tar.xz/src/sua.c -> libosmo-sigtran_2.1.0.38.7781.tar.xz/src/sua.c
Changed
@@ -291,13 +291,16 @@ static int sua_tx_xua_asp(struct osmo_ss7_asp *asp, struct xua_msg *xua) { - struct msgb *msg = sua_to_msg(xua); + struct msgb *msg; OSMO_ASSERT(asp->cfg.proto == OSMO_SS7_ASP_PROT_SUA); + msg = sua_to_msg(xua); + xua_msg_free(xua); if (!msg) return -1; + /* msg becomes owned by osmo_ss7_asp_send here: */ return osmo_ss7_asp_send(asp, msg); } @@ -307,7 +310,6 @@ * \return 0 on success; negative on error */ int sua_tx_xua_as(struct osmo_ss7_as *as, struct xua_msg *xua) { - struct msgb *msg; int rc; OSMO_ASSERT(as->cfg.proto == OSMO_SS7_ASP_PROT_SUA); @@ -316,17 +318,11 @@ if (as->cfg.routing_key.context) xua_msg_add_u32(xua, SUA_IEI_ROUTE_CTX, as->cfg.routing_key.context); - msg = sua_to_msg(xua); - if (!msg) { - LOGPAS(as, DLSUA, LOGL_ERROR, "Error encoding SUA Msg\n"); - return -1; - } - /* send the msg to the AS for transmission. The AS FSM might * (depending on its state) enqueue it before transmission */ - rc = osmo_fsm_inst_dispatch(as->fi, XUA_AS_E_TRANSFER_REQ, msg); + rc = osmo_fsm_inst_dispatch(as->fi, XUA_AS_E_TRANSFER_REQ, xua); if (rc < 0) - msgb_free(msg); + xua_msg_free(xua); return rc; } @@ -534,6 +530,8 @@ return rc; rate_ctr_inc2(as->ctrg, SS7_AS_CTR_RX_MSU_TOTAL); + OSMO_ASSERT(xua->mtp.sls <= 0xf); + rate_ctr_inc2(as->ctrg, SS7_AS_CTR_RX_MSU_SLS_0 + xua->mtp.sls); switch (xua->hdr.msg_type) { case 0: /* Reserved, permitted by ETSI TS 101 592 5.2.3.2 */ @@ -564,6 +562,8 @@ return rc; rate_ctr_inc2(as->ctrg, SS7_AS_CTR_RX_MSU_TOTAL); + OSMO_ASSERT(xua->mtp.sls <= 0xf); + rate_ctr_inc2(as->ctrg, SS7_AS_CTR_RX_MSU_SLS_0 + xua->mtp.sls); switch (xua->hdr.msg_type) { case 0: /* Reserved, permitted by ETSI TS 101 592 5.2.3.2 */
View file
libosmo-sigtran_2.1.0.28.3099.tar.xz/src/xua_as_fsm.c -> libosmo-sigtran_2.1.0.38.7781.tar.xz/src/xua_as_fsm.c
Changed
@@ -121,13 +121,29 @@ return -1; } -int xua_as_transmit_msg_broadcast(struct osmo_ss7_as *as, struct msgb *msg) +static struct msgb *xua_as_encode_msg(const struct osmo_ss7_as *as, struct xua_msg *xua) +{ + switch (as->cfg.proto) { + case OSMO_SS7_ASP_PROT_M3UA: + return m3ua_to_msg(xua); + case OSMO_SS7_ASP_PROT_IPA: + return ipa_to_msg(xua); + default: + OSMO_ASSERT(0); + } +} + +int xua_as_transmit_msg_broadcast(struct osmo_ss7_as *as, struct xua_msg *xua) { struct osmo_ss7_asp *asp; unsigned int i; + struct msgb *msg; struct msgb *msg_cpy; bool sent = false; + msg = xua_as_encode_msg(as, xua); + OSMO_ASSERT(msg); + for (i = 0; i < ARRAY_SIZE(as->cfg.asps); i++) { asp = as->cfg.aspsi; if (!asp || !osmo_ss7_asp_active(asp)) @@ -138,35 +154,41 @@ } msgb_free(msg); + xua_msg_free(xua); return sent ? 0 : -1; } /* actually transmit a message through this AS */ -int xua_as_transmit_msg(struct osmo_ss7_as *as, struct msgb *msg) +int xua_as_transmit_msg(struct osmo_ss7_as *as, struct xua_msg *xua) { struct osmo_ss7_asp *asp = NULL; + struct msgb *msg; switch (as->cfg.mode) { case OSMO_SS7_AS_TMOD_OVERRIDE: case OSMO_SS7_AS_TMOD_LOADSHARE: /* TODO: OSMO_SS7_AS_TMOD_LOADSHARE: actually use the SLS value - * to ensure same SLS goes through same ASP. Not strictly - * required by M3UA RFC, but would fit the overall principle. */ + * in xua->mtp.sls to ensure same SLS goes through same ASP. Not + * strictly required by M3UA RFC, but would fit the overall + * principle. */ case OSMO_SS7_AS_TMOD_ROUNDROBIN: - asp = osmo_ss7_as_select_asp(as); + asp = ss7_as_select_asp(as, &xua->mtp); break; case OSMO_SS7_AS_TMOD_BCAST: - return xua_as_transmit_msg_broadcast(as, msg); + return xua_as_transmit_msg_broadcast(as, xua); case _NUM_OSMO_SS7_ASP_TMOD: OSMO_ASSERT(false); } if (!asp) { LOGPFSM(as->fi, "No ASP in AS, dropping message\n"); - msgb_free(msg); + xua_msg_free(xua); return -1; } + msg = xua_as_encode_msg(as, xua); + OSMO_ASSERT(msg); + xua_msg_free(xua); return osmo_ss7_asp_send(asp, msg); } @@ -192,7 +214,7 @@ struct osmo_ss7_as *as; struct { struct osmo_timer_list t_r; - struct llist_head queued_msgs; + struct llist_head queued_xua_msgs; } recovery; bool ipa_route_created; }; @@ -481,7 +503,7 @@ struct xua_as_fsm_priv *xafp = (struct xua_as_fsm_priv *) fi->priv; struct osmo_ss7_asp *asp; struct xua_as_event_asp_inactive_ind_pars *inact_ind_pars; - struct msgb *msg; + struct xua_msg *xua; struct osmo_xlm_prim_notify npar; switch (event) { @@ -510,8 +532,8 @@ break; case XUA_AS_E_TRANSFER_REQ: /* message for transmission */ - msg = data; - xua_as_transmit_msg(xafp->as, msg); + xua = data; + xua_as_transmit_msg(xafp->as, xua); break; } } @@ -520,7 +542,7 @@ { struct xua_as_fsm_priv *xafp = (struct xua_as_fsm_priv *) fi->priv; struct xua_as_event_asp_inactive_ind_pars *inact_ind_pars; - struct msgb *msg; + struct xua_msg *xua; struct osmo_xlm_prim_notify npar; switch (event) { @@ -529,8 +551,12 @@ osmo_timer_del(&xafp->recovery.t_r); osmo_fsm_inst_state_chg(fi, XUA_AS_S_ACTIVE, 0, 0); /* push out any pending queued messages */ - while ((msg = msgb_dequeue(&xafp->recovery.queued_msgs))) - xua_as_transmit_msg(xafp->as, msg); + while (!llist_empty(&xafp->recovery.queued_xua_msgs)) { + struct xua_msg *xua; + xua = llist_first_entry(&xafp->recovery.queued_xua_msgs, struct xua_msg, entry); + llist_del(&xua->entry); + xua_as_transmit_msg(xafp->as, xua); + } break; case XUA_ASPAS_ASP_INACTIVE_IND: inact_ind_pars = data; @@ -544,8 +570,12 @@ break; case XUA_AS_E_RECOVERY_EXPD: LOGPFSM(fi, "T(r) expired; dropping queued messages\n"); - while ((msg = msgb_dequeue(&xafp->recovery.queued_msgs))) - talloc_free(msg); + while (!llist_empty(&xafp->recovery.queued_xua_msgs)) { + struct xua_msg *xua; + xua = llist_first_entry(&xafp->recovery.queued_xua_msgs, struct xua_msg, entry); + llist_del(&xua->entry); + xua_msg_free(xua); + } if (check_any_other_asp_not_down(xafp->as, NULL)) osmo_fsm_inst_state_chg(fi, XUA_AS_S_INACTIVE, 0, 0); else @@ -553,8 +583,8 @@ break; case XUA_AS_E_TRANSFER_REQ: /* enqueue the to-be-transferred message */ - msg = data; - msgb_enqueue(&xafp->recovery.queued_msgs, msg); + xua = data; + llist_add_tail(&xua->entry, &xafp->recovery.queued_xua_msgs); break; } } @@ -642,7 +672,7 @@ xafp->as = as; xafp->recovery.t_r.cb = t_r_callback; xafp->recovery.t_r.data = fi; - INIT_LLIST_HEAD(&xafp->recovery.queued_msgs); + INIT_LLIST_HEAD(&xafp->recovery.queued_xua_msgs); fi->priv = xafp;
View file
libosmo-sigtran_2.1.0.28.3099.tar.xz/src/xua_as_fsm.h -> libosmo-sigtran_2.1.0.38.7781.tar.xz/src/xua_as_fsm.h
Changed
@@ -24,7 +24,7 @@ XUA_ASPAS_ASP_DOWN_IND, XUA_ASPAS_ASP_ACTIVE_IND, XUA_AS_E_RECOVERY_EXPD, - XUA_AS_E_TRANSFER_REQ, + XUA_AS_E_TRANSFER_REQ, /* param: struct xua_msg*, ownership transferred. */ }; extern struct osmo_fsm xua_as_fsm;
View file
libosmo-sigtran_2.1.0.28.3099.tar.xz/src/xua_internal.h -> libosmo-sigtran_2.1.0.38.7781.tar.xz/src/xua_internal.h
Changed
@@ -33,6 +33,7 @@ struct osmo_mtp_prim *m3ua_to_xfer_ind(struct xua_msg *xua); int m3ua_hmdc_rx_from_l2(struct osmo_ss7_instance *inst, struct xua_msg *xua); +struct msgb *m3ua_to_msg(struct xua_msg *xua); 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, @@ -114,11 +115,12 @@ #define PC_STR "Point Code\n" #define INST_STR "An instance of the SS7 stack\n" -int xua_as_transmit_msg(struct osmo_ss7_as *as, struct msgb *msg); +int xua_as_transmit_msg(struct osmo_ss7_as *as, struct xua_msg *xua); int xua_find_as_for_asp(struct osmo_ss7_as **as, const struct osmo_ss7_asp *asp, const struct xua_msg_part *rctx_ie); +struct msgb *ipa_to_msg(struct xua_msg *xua); int ipa_tx_xua_as(struct osmo_ss7_as *as, struct xua_msg *xua); int ipa_rx_msg(struct osmo_ss7_asp *asp, struct msgb *msg, uint8_t sls); struct osmo_ss7_as *ipa_find_as_for_asp(struct osmo_ss7_asp *asp);
View file
libosmo-sigtran_2.1.0.28.3099.tar.xz/src/xua_msg.h -> libosmo-sigtran_2.1.0.38.7781.tar.xz/src/xua_msg.h
Changed
@@ -29,6 +29,7 @@ struct osmo_sccp_gt; struct xua_msg { + struct llist_head entry; /* Allows queueing a xua_msg into a llist */ struct xua_common_hdr hdr; struct osmo_mtp_transfer_param mtp;
View file
libosmo-sigtran_2.1.0.28.3099.tar.xz/src/xua_rkm.c -> libosmo-sigtran_2.1.0.38.7781.tar.xz/src/xua_rkm.c
Changed
@@ -393,7 +393,7 @@ return -1; } - rt = ss7_route_table_find_route_by_dpc(inst->rtable_system, as->cfg.routing_key.pc); + rt = ss7_route_table_find_route_by_dpc_mask(inst->rtable_system, as->cfg.routing_key.pc, 0xffffff); if (!rt) { msgb_append_dereg_res(resp, M3UA_RKM_DEREG_ERR_UNKNOWN, 0); return -1; @@ -548,7 +548,8 @@ return 0; } -/* process an incoming RKM message in xua format */ +/* process an incoming RKM message in xua format + * This function takes ownership of xua msg passed to it. */ int m3ua_rx_rkm(struct osmo_ss7_asp *asp, struct xua_msg *xua) { int rc; @@ -578,6 +579,8 @@ rc = -1; break; } + + xua_msg_free(xua); return rc; }
View file
libosmo-sigtran_2.1.0.28.3099.tar.xz/src/xua_snm.c -> libosmo-sigtran_2.1.0.38.7781.tar.xz/src/xua_snm.c
Changed
@@ -34,6 +34,7 @@ #include "ss7_as.h" #include "ss7_asp.h" #include "ss7_internal.h" +#include "ss7_route_table.h" #include "xua_internal.h" #include "sccp_internal.h" @@ -340,8 +341,14 @@ if (mask == 0) { /* one single point code */ - /* FIXME: don't just check for a route; but also check if the route is "active" */ - if (osmo_ss7_route_lookup(s7i, pc)) + struct osmo_ss7_route_label rtlabel = { + .opc = xua->mtp.opc, /* Use OPC of received DAUD. FIXME: is this correct? */ + .dpc = pc, + .sls = 0, + }; + + /* Check if there's an "active" route available: */ + if (ss7_instance_lookup_route(s7i, &rtlabel)) is_available = true; xua_tx_snm_available(asp, rctx, num_rctx, &aff_pci, 1, "Response to DAUD",
View file
libosmo-sigtran_2.1.0.28.3099.tar.xz/tests/ss7/ss7_test.c -> libosmo-sigtran_2.1.0.38.7781.tar.xz/tests/ss7/ss7_test.c
Changed
@@ -147,11 +147,16 @@ osmo_ss7_user_destroy(user2); } +#define RT_LABEL(opc_val, dpc_val, sls_val) \ + (struct osmo_ss7_route_label){ .opc = (opc_val), .dpc = (dpc_val), .sls = (sls_val) } + static void test_route(void) { struct osmo_ss7_route_table *rtbl; struct osmo_ss7_linkset *lset_a, *lset_b; + struct osmo_ss7_link *l_a, *l_b; struct osmo_ss7_route *rt, *rt12, *rtdef; + struct osmo_ss7_route_label route_label; printf("Testing SS7 routing\n"); @@ -169,36 +174,56 @@ lset_a = ss7_linkset_find_or_create(s7i, "a", 100); OSMO_ASSERT(lset_a); + l_a = ss7_link_find_or_create(lset_a, 0); + OSMO_ASSERT(l_a); + l_a->cfg.adm_state = OSMO_SS7_LS_ENABLED; + lset_b = ss7_linkset_find_or_create(s7i, "b", 200); OSMO_ASSERT(lset_b); + l_b = ss7_link_find_or_create(lset_b, 0); + OSMO_ASSERT(l_b); + l_b->cfg.adm_state = OSMO_SS7_LS_ENABLED; /* route with full mask */ - OSMO_ASSERT(ss7_route_table_find_route_by_dpc(rtbl, 12) == NULL); + route_label = RT_LABEL(0, 12, 0); + OSMO_ASSERT(ss7_route_table_lookup_route(rtbl, &route_label) == NULL); rt = ss7_route_create(rtbl, 12, 0xffff, "a"); printf("route with full mask: %s\n", osmo_ss7_route_print(rt)); OSMO_ASSERT(rt); - OSMO_ASSERT(ss7_route_table_find_route_by_dpc(rtbl, 12) == rt); + route_label = RT_LABEL(0, 12, 0); + OSMO_ASSERT(ss7_route_table_lookup_route(rtbl, &route_label) == rt); ss7_route_destroy(rt); /* route with partial mask */ rt = ss7_route_create(rtbl, 8, 0xfff8, "a"); printf("route with partial mask: %s\n", osmo_ss7_route_print(rt)); - OSMO_ASSERT(ss7_route_table_find_route_by_dpc(rtbl, 8) == rt); - OSMO_ASSERT(ss7_route_table_find_route_by_dpc(rtbl, 9) == rt); - OSMO_ASSERT(ss7_route_table_find_route_by_dpc(rtbl, 12) == rt); - OSMO_ASSERT(ss7_route_table_find_route_by_dpc(rtbl, 15) == rt); - OSMO_ASSERT(ss7_route_table_find_route_by_dpc(rtbl, 16) == NULL); + route_label = RT_LABEL(0, 8, 0); + OSMO_ASSERT(ss7_route_table_lookup_route(rtbl, &route_label) == rt); + route_label = RT_LABEL(0, 9, 0); + OSMO_ASSERT(ss7_route_table_lookup_route(rtbl, &route_label) == rt); + route_label = RT_LABEL(0, 12, 0); + OSMO_ASSERT(ss7_route_table_lookup_route(rtbl, &route_label) == rt); + route_label = RT_LABEL(0, 15, 0); + OSMO_ASSERT(ss7_route_table_lookup_route(rtbl, &route_label) == rt); + route_label = RT_LABEL(0, 16, 0); + OSMO_ASSERT(ss7_route_table_lookup_route(rtbl, &route_label) == NULL); /* insert more specific route for 12, must have higher priority * than existing one */ rt12 = ss7_route_create(rtbl, 12, 0xffff, "b"); - OSMO_ASSERT(ss7_route_table_find_route_by_dpc(rtbl, 12) == rt12); - OSMO_ASSERT(ss7_route_table_find_route_by_dpc(rtbl, 15) == rt); - OSMO_ASSERT(ss7_route_table_find_route_by_dpc(rtbl, 16) == NULL); + route_label = RT_LABEL(0, 12, 0); + OSMO_ASSERT(ss7_route_table_lookup_route(rtbl, &route_label) == rt12); + route_label = RT_LABEL(0, 15, 0); + OSMO_ASSERT(ss7_route_table_lookup_route(rtbl, &route_label) == rt); + route_label = RT_LABEL(0, 16, 0); + OSMO_ASSERT(ss7_route_table_lookup_route(rtbl, &route_label) == NULL); /* add a default route, which should have lowest precedence */ rtdef = ss7_route_create(rtbl, 0, 0, "a"); - OSMO_ASSERT(ss7_route_table_find_route_by_dpc(rtbl, 12) == rt12); - OSMO_ASSERT(ss7_route_table_find_route_by_dpc(rtbl, 15) == rt); - OSMO_ASSERT(ss7_route_table_find_route_by_dpc(rtbl, 16) == rtdef); + route_label = RT_LABEL(0, 12, 0); + OSMO_ASSERT(ss7_route_table_lookup_route(rtbl, &route_label) == rt12); + route_label = RT_LABEL(0, 15, 0); + OSMO_ASSERT(ss7_route_table_lookup_route(rtbl, &route_label) == rt); + route_label = RT_LABEL(0, 16, 0); + OSMO_ASSERT(ss7_route_table_lookup_route(rtbl, &route_label) == rtdef); ss7_route_destroy(rtdef); ss7_route_destroy(rt12);
View file
libosmo-sigtran_2.1.0.28.3099.tar.xz/tests/vty/osmo_stp_route_prio.vty -> libosmo-sigtran_2.1.0.38.7781.tar.xz/tests/vty/osmo_stp_route_prio.vty
Changed
@@ -87,6 +87,6 @@ 3.2.1/14 INACC 0 5 as2 UNAVAIL ? UNAVAIL 3.2.1/14 INACC 7 6 as1 UNAVAIL ? UNAVAIL -OsmoSTP(config-cs7-rt)# ! NOW TEST LOOKUP WORKS AS DESIRED (as3 PICKED): +OsmoSTP(config-cs7-rt)# ! NOW TEST LOOKUP FAILS AS EXPECTED (all route links are down): OsmoSTP(config-cs7-rt)# do show cs7 instance 0 route-lookup 3.2.1 from 0.0.1 sls 0 -pc=6161=3.2.1 mask=0x3fff=7.255.7 via AS as3 proto=m3ua +No route found for label 'OPC=1=0.0.1,DPC=6161=3.2.1,SLS=0'
View file
libosmo-sigtran_2.1.0.28.3099.tar.xz/tests/vty/osmo_stp_test.vty -> libosmo-sigtran_2.1.0.38.7781.tar.xz/tests/vty/osmo_stp_test.vty
Changed
@@ -112,6 +112,8 @@ point-code format default point-code delimiter (default|dash) xua rkm routing-key-allocation (static-only|dynamic-permitted) + sls-opc-dpc opc-shift <0-8> dpc-shift <0-8> + sls-shift <0-6> asp NAME <0-65535> <0-65535> (sua|m3ua|ipa) asp NAME <0-65535> <0-65535> (sua|m3ua|ipa) (sctp|tcp) no asp NAME @@ -132,6 +134,8 @@ point-code Configure the local Point Code secondary-pc Configure the local Secondary Point Code xua SIGTRAN xxxUA related + sls-opc-dpc Shift OPC and DPC bits used during routing decision + sls-shift Shift SLS bits used during routing decision asp Configure Application Server Process no Negate a command or set its defaults as Configure an Application Server @@ -347,8 +351,10 @@ description .TEXT asp NAME no asp NAME - traffic-mode (broadcast | loadshare | roundrobin | override) + traffic-mode (broadcast | roundrobin | override) + traffic-mode loadshare bindings sls opc-sls opc-shift <0-2> no traffic-mode + sls-shift <0-3> recovery-timeout <1-2000> qos-class <0-7> routing-key RCONTEXT DPC @@ -364,6 +370,7 @@ asp Specify that a given ASP is part of this AS no Negate a command or set its defaults traffic-mode Specifies traffic mode of operation of the ASP within the AS + sls-shift Shift SLS bits used during routing decision recovery-timeout Specifies the recovery timeout value in milliseconds qos-class Specity QoS Class of AS routing-key Define a routing key
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.