libosmo-sccp/src/sccp_internal.h

140 lines
4.5 KiB
C
Raw Normal View History

#pragma once
#include <osmocom/core/fsm.h>
#include <osmocom/core/prim.h>
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/linuxrbtree.h>
#include <osmocom/core/tdef.h>
#include <osmocom/sigtran/sccp_sap.h>
#include <osmocom/sigtran/osmo_ss7.h>
#include <osmocom/sigtran/protocol/mtp.h>
#define SCCP_STR "Signalling Connection Control Part\n"
make SCCP timers configurable The previous hardcoded SCCP timers may cause SCCP connection releases, if the peer is configured with far lower timers than libosmo-sccp. Testing with a specific SCCPlite MSC, I experienced an iar of just over three minutes, meaning that calls would be cut off by the MSC, since the osmo-bsc failed to send an Inactivity Timer message until seven minutes have passed. With this patch, SCCP timers are configurable by the user. Define constant global default timers, and variable user-configurable timers with each osmo_sccp_instance. Add VTY UI to configure the timers. Users must call osmo_sccp_vty_init() to get the sccp-timer config nodes under the 'cs7' node. Show the new UI in ss7_asp_test.vty. Note that even though this function is not new at all, until recently, all of our SCCP users (osmo-bsc, osmo-msc, osmo-sgsn, osmo-hnbgw) failed to call osmo_sccp_vty_init(), and thus also missed out on the various 'show' commands defined in sccp_vty.c. In other words, to benefit from the timer configurability, the patches to call osmo_sccp_vty_init() must first be merged to the corresponding master branches. If a 'sccp-timer' config command occurs, the cs7 instance must allocate an SCCP instance in order to store the timer config. Do that by calling the recently added osmo_ss7_ensure_sccp() function. Hence remove the limitation that the SCCP instance must not be populated from the "simple" setup function. If we want to configure SCCP timers beforehand, there must be an SCCP instance for that, and there is no hard reason to require a NULL SCCP instance, besides the desire to prevent this function from being invoked twice. Change-Id: I28a7362aa838e648ecc9b26ee53dbcade81a9d65
2018-09-26 15:12:23 +00:00
/* Appendix C.4 of Q.714 */
enum osmo_sccp_timer {
/* 0 kept unused on purpose since it's handled specially by osmo_fsm */
OSMO_SCCP_TIMER_CONN_EST = 1,
make SCCP timers configurable The previous hardcoded SCCP timers may cause SCCP connection releases, if the peer is configured with far lower timers than libosmo-sccp. Testing with a specific SCCPlite MSC, I experienced an iar of just over three minutes, meaning that calls would be cut off by the MSC, since the osmo-bsc failed to send an Inactivity Timer message until seven minutes have passed. With this patch, SCCP timers are configurable by the user. Define constant global default timers, and variable user-configurable timers with each osmo_sccp_instance. Add VTY UI to configure the timers. Users must call osmo_sccp_vty_init() to get the sccp-timer config nodes under the 'cs7' node. Show the new UI in ss7_asp_test.vty. Note that even though this function is not new at all, until recently, all of our SCCP users (osmo-bsc, osmo-msc, osmo-sgsn, osmo-hnbgw) failed to call osmo_sccp_vty_init(), and thus also missed out on the various 'show' commands defined in sccp_vty.c. In other words, to benefit from the timer configurability, the patches to call osmo_sccp_vty_init() must first be merged to the corresponding master branches. If a 'sccp-timer' config command occurs, the cs7 instance must allocate an SCCP instance in order to store the timer config. Do that by calling the recently added osmo_ss7_ensure_sccp() function. Hence remove the limitation that the SCCP instance must not be populated from the "simple" setup function. If we want to configure SCCP timers beforehand, there must be an SCCP instance for that, and there is no hard reason to require a NULL SCCP instance, besides the desire to prevent this function from being invoked twice. Change-Id: I28a7362aa838e648ecc9b26ee53dbcade81a9d65
2018-09-26 15:12:23 +00:00
OSMO_SCCP_TIMER_IAS,
OSMO_SCCP_TIMER_IAR,
OSMO_SCCP_TIMER_REL,
OSMO_SCCP_TIMER_REPEAT_REL,
OSMO_SCCP_TIMER_INT,
OSMO_SCCP_TIMER_GUARD,
OSMO_SCCP_TIMER_RESET,
OSMO_SCCP_TIMER_REASSEMBLY,
/* This must remain the last item: */
OSMO_SCCP_TIMERS_LEN
make SCCP timers configurable The previous hardcoded SCCP timers may cause SCCP connection releases, if the peer is configured with far lower timers than libosmo-sccp. Testing with a specific SCCPlite MSC, I experienced an iar of just over three minutes, meaning that calls would be cut off by the MSC, since the osmo-bsc failed to send an Inactivity Timer message until seven minutes have passed. With this patch, SCCP timers are configurable by the user. Define constant global default timers, and variable user-configurable timers with each osmo_sccp_instance. Add VTY UI to configure the timers. Users must call osmo_sccp_vty_init() to get the sccp-timer config nodes under the 'cs7' node. Show the new UI in ss7_asp_test.vty. Note that even though this function is not new at all, until recently, all of our SCCP users (osmo-bsc, osmo-msc, osmo-sgsn, osmo-hnbgw) failed to call osmo_sccp_vty_init(), and thus also missed out on the various 'show' commands defined in sccp_vty.c. In other words, to benefit from the timer configurability, the patches to call osmo_sccp_vty_init() must first be merged to the corresponding master branches. If a 'sccp-timer' config command occurs, the cs7 instance must allocate an SCCP instance in order to store the timer config. Do that by calling the recently added osmo_ss7_ensure_sccp() function. Hence remove the limitation that the SCCP instance must not be populated from the "simple" setup function. If we want to configure SCCP timers beforehand, there must be an SCCP instance for that, and there is no hard reason to require a NULL SCCP instance, besides the desire to prevent this function from being invoked twice. Change-Id: I28a7362aa838e648ecc9b26ee53dbcade81a9d65
2018-09-26 15:12:23 +00:00
};
extern const struct osmo_tdef osmo_sccp_timer_defaults[OSMO_SCCP_TIMERS_LEN];
make SCCP timers configurable The previous hardcoded SCCP timers may cause SCCP connection releases, if the peer is configured with far lower timers than libosmo-sccp. Testing with a specific SCCPlite MSC, I experienced an iar of just over three minutes, meaning that calls would be cut off by the MSC, since the osmo-bsc failed to send an Inactivity Timer message until seven minutes have passed. With this patch, SCCP timers are configurable by the user. Define constant global default timers, and variable user-configurable timers with each osmo_sccp_instance. Add VTY UI to configure the timers. Users must call osmo_sccp_vty_init() to get the sccp-timer config nodes under the 'cs7' node. Show the new UI in ss7_asp_test.vty. Note that even though this function is not new at all, until recently, all of our SCCP users (osmo-bsc, osmo-msc, osmo-sgsn, osmo-hnbgw) failed to call osmo_sccp_vty_init(), and thus also missed out on the various 'show' commands defined in sccp_vty.c. In other words, to benefit from the timer configurability, the patches to call osmo_sccp_vty_init() must first be merged to the corresponding master branches. If a 'sccp-timer' config command occurs, the cs7 instance must allocate an SCCP instance in order to store the timer config. Do that by calling the recently added osmo_ss7_ensure_sccp() function. Hence remove the limitation that the SCCP instance must not be populated from the "simple" setup function. If we want to configure SCCP timers beforehand, there must be an SCCP instance for that, and there is no hard reason to require a NULL SCCP instance, besides the desire to prevent this function from being invoked twice. Change-Id: I28a7362aa838e648ecc9b26ee53dbcade81a9d65
2018-09-26 15:12:23 +00:00
extern const struct value_string osmo_sccp_timer_names[];
static inline const char *osmo_sccp_timer_name(enum osmo_sccp_timer val)
{ return get_value_string(osmo_sccp_timer_names, val); }
/* an instance of the SCCP stack */
struct osmo_sccp_instance {
/* entry in global list of ss7 instances */
struct llist_head list;
/* rbtree root of 'struct sccp_connection' in this instance */
struct rb_root connections;
/* list of SCCP users in this instance */
struct llist_head users;
/* routing context to be used in all outbound messages */
uint32_t route_ctx;
/* next connection ID to allocate */
uint32_t next_id;
struct osmo_ss7_instance *ss7;
void *priv;
struct osmo_ss7_user ss7_user;
make SCCP timers configurable The previous hardcoded SCCP timers may cause SCCP connection releases, if the peer is configured with far lower timers than libosmo-sccp. Testing with a specific SCCPlite MSC, I experienced an iar of just over three minutes, meaning that calls would be cut off by the MSC, since the osmo-bsc failed to send an Inactivity Timer message until seven minutes have passed. With this patch, SCCP timers are configurable by the user. Define constant global default timers, and variable user-configurable timers with each osmo_sccp_instance. Add VTY UI to configure the timers. Users must call osmo_sccp_vty_init() to get the sccp-timer config nodes under the 'cs7' node. Show the new UI in ss7_asp_test.vty. Note that even though this function is not new at all, until recently, all of our SCCP users (osmo-bsc, osmo-msc, osmo-sgsn, osmo-hnbgw) failed to call osmo_sccp_vty_init(), and thus also missed out on the various 'show' commands defined in sccp_vty.c. In other words, to benefit from the timer configurability, the patches to call osmo_sccp_vty_init() must first be merged to the corresponding master branches. If a 'sccp-timer' config command occurs, the cs7 instance must allocate an SCCP instance in order to store the timer config. Do that by calling the recently added osmo_ss7_ensure_sccp() function. Hence remove the limitation that the SCCP instance must not be populated from the "simple" setup function. If we want to configure SCCP timers beforehand, there must be an SCCP instance for that, and there is no hard reason to require a NULL SCCP instance, besides the desire to prevent this function from being invoked twice. Change-Id: I28a7362aa838e648ecc9b26ee53dbcade81a9d65
2018-09-26 15:12:23 +00:00
struct osmo_tdef *tdefs;
uint32_t max_optional_data;
};
struct osmo_sccp_user {
/*! \brief entry in list of sccp users of \ref osmo_sccp_instance */
struct llist_head list;
/*! \brief pointer back to SCCP instance */
struct osmo_sccp_instance *inst;
/*! \brief human-readable name of this user */
char *name;
/*! \brief SSN and/or point code to which we are bound */
uint16_t ssn;
uint32_t pc;
/* set if we are a server */
struct llist_head links;
/* user call-back function in case of incoming primitives */
osmo_prim_cb prim_cb;
void *priv;
/* Application Server FSM Instance */
struct osmo_fsm_inst *as_fi;
};
extern int DSCCP;
struct xua_msg;
struct osmo_sccp_user *
sccp_user_find(struct osmo_sccp_instance *inst, uint16_t ssn, uint32_t pc);
/* Message from SCOC -> SCRC */
int sccp_scrc_rx_scoc_conn_msg(struct osmo_sccp_instance *inst,
struct xua_msg *xua);
/* Message from SCLC -> SCRC */
int sccp_scrc_rx_sclc_msg(struct osmo_sccp_instance *inst, struct xua_msg *xua);
/* Message from MTP (SUA) -> SCRC */
int scrc_rx_mtp_xfer_ind_xua(struct osmo_sccp_instance *inst,
struct xua_msg *xua);
/* Message from SCRC -> SCOC */
void sccp_scoc_rx_from_scrc(struct osmo_sccp_instance *inst,
struct xua_msg *xua);
void sccp_scoc_rx_scrc_rout_fail(struct osmo_sccp_instance *inst,
struct xua_msg *xua, uint32_t cause);
void sccp_scoc_flush_connections(struct osmo_sccp_instance *inst);
/* Message from SCRC -> SCLC */
int sccp_sclc_rx_from_scrc(struct osmo_sccp_instance *inst,
struct xua_msg *xua);
void sccp_sclc_rx_scrc_rout_fail(struct osmo_sccp_instance *inst,
struct xua_msg *xua, uint32_t cause);
int sccp_user_prim_up(struct osmo_sccp_user *scut, struct osmo_scu_prim *prim);
/* SCU -> SCLC */
int sccp_sclc_user_sap_down(struct osmo_sccp_user *scu, struct osmo_prim_hdr *oph);
add caller-owns-msgb variant osmo_sccp_user_sap_down_nofree() Add osmo_sccp_user_sap_down_nofree(), which is identical to osmo_sccp_user_sap_down(), but doesn't imply a msgb_free(). To implement that, sccp_sclc_user_sap_down_nofree() with the same msgb semantics is required. Rationale: Avoiding msgb leaks is easiest if the caller retains ownership of the msgb. Take this hypothetical chain where leaks are obviously avoided: void send() { msg = msgb_alloc(); dispatch(msg); msgb_free(msg); } void dispatch(msg) { osmo_fsm_inst_dispatch(fi, msg); } void fi_on_event(fi, data) { if (socket_is_ok) socket_write((struct msgb*)data); } void socket_write(msgb) { if (!ok1) return; if (ok2) { if (!ok3) return; write(sock, msg->data); } } However, if the caller passes ownership down to the msgb consumer, things become nightmarishly complex: void send() { msg = msgb_alloc(); rc = dispatch(msg); /* dispatching event failed? */ if (rc) msgb_free(msg); } int dispatch(msg) { if (osmo_fsm_inst_dispatch(fi, msg)) return -1; if (something_else()) return -1; // <-- double free! } void fi_on_event(fi, data) { if (socket_is_ok) { socket_write((struct msgb*)data); else /* socket didn't consume? */ msgb_free(data); } int socket_write(msgb) { if (!ok1) return -1; // <-- leak! if (ok2) { if (!ok3) goto out; write(sock, msg->data); } out: msgb_free(msg); return -2; } If any link in this call chain fails to be aware of the importance to return a failed RC or to free a msgb if the chain is broken, or to not return a failed RC if the msgb is consumed, we have a hidden msgb leak or double free. This is the case with osmo_sccp_user_sap_down(). In new osmo-msc, passing data through various FSM instances, there is high potential for leak/double-free bugs. A very large brain is required to track down every msgb path. osmo_sccp_user_sap_down_nofree() makes this problem trivial to solve even for humans. Change-Id: Ic818efa78b90f727e1a94c18b60d9a306644f340
2019-03-10 03:41:27 +00:00
int sccp_sclc_user_sap_down_nofree(struct osmo_sccp_user *scu, struct osmo_prim_hdr *oph);
struct msgb *sccp_msgb_alloc(const char *name);
extern struct osmo_fsm sccp_scoc_fsm;
void sccp_scoc_show_connections(struct vty *vty, struct osmo_sccp_instance *inst);
make SCCP timers configurable The previous hardcoded SCCP timers may cause SCCP connection releases, if the peer is configured with far lower timers than libosmo-sccp. Testing with a specific SCCPlite MSC, I experienced an iar of just over three minutes, meaning that calls would be cut off by the MSC, since the osmo-bsc failed to send an Inactivity Timer message until seven minutes have passed. With this patch, SCCP timers are configurable by the user. Define constant global default timers, and variable user-configurable timers with each osmo_sccp_instance. Add VTY UI to configure the timers. Users must call osmo_sccp_vty_init() to get the sccp-timer config nodes under the 'cs7' node. Show the new UI in ss7_asp_test.vty. Note that even though this function is not new at all, until recently, all of our SCCP users (osmo-bsc, osmo-msc, osmo-sgsn, osmo-hnbgw) failed to call osmo_sccp_vty_init(), and thus also missed out on the various 'show' commands defined in sccp_vty.c. In other words, to benefit from the timer configurability, the patches to call osmo_sccp_vty_init() must first be merged to the corresponding master branches. If a 'sccp-timer' config command occurs, the cs7 instance must allocate an SCCP instance in order to store the timer config. Do that by calling the recently added osmo_ss7_ensure_sccp() function. Hence remove the limitation that the SCCP instance must not be populated from the "simple" setup function. If we want to configure SCCP timers beforehand, there must be an SCCP instance for that, and there is no hard reason to require a NULL SCCP instance, besides the desire to prevent this function from being invoked twice. Change-Id: I28a7362aa838e648ecc9b26ee53dbcade81a9d65
2018-09-26 15:12:23 +00:00
void osmo_sccp_vty_write_cs7_node(struct vty *vty, const char *indent, struct osmo_sccp_instance *inst);
/* Local Broadcast (LBCS) */
void sccp_lbcs_local_bcast_pcstate(struct osmo_sccp_instance *inst,
const struct osmo_scu_pcstate_param *pcstate);
void sccp_lbcs_local_bcast_state(struct osmo_sccp_instance *inst,
const struct osmo_scu_state_param *state);
/* SCCP Management (SCMG) */
void sccp_scmg_rx_ssn_allowed(struct osmo_sccp_instance *inst, uint32_t dpc, uint32_t ssn, uint32_t smi);
void sccp_scmg_rx_ssn_prohibited(struct osmo_sccp_instance *inst, uint32_t dpc, uint32_t ssn, uint32_t smi);
void sccp_scmg_rx_mtp_pause(struct osmo_sccp_instance *inst, uint32_t dpc);
void sccp_scmg_rx_mtp_resume(struct osmo_sccp_instance *inst, uint32_t dpc);
void sccp_scmg_rx_mtp_status(struct osmo_sccp_instance *inst, uint32_t dpc, enum mtp_unavail_cause cause);
int sccp_scmg_init(struct osmo_sccp_instance *inst);