neels has submitted this change. ( https://gerrit.osmocom.org/c/osmo-hnbgw/+/32323 )
Change subject: cnpool: allow separate cs7 for IuPS and IuCS ......................................................................
cnpool: allow separate cs7 for IuPS and IuCS
Prepare for CN pooling; allow using separate SS7 instances for IuCS and IuPS.
New struct hnbgw_sccp_user describes a RANAP SCCP user, one per cs7. Limit struct hnbgw_cnlink to describing a CN peer, using whichever SCCP instance that is indicated by hnbgw_sccp_user.
Chart sccp.dot shows the changes made.
Related: SYS#6412 Change-Id: Iea1824f1c586723d989c80a909bae16bd2866e08 --- M doc/charts/sccp.dot M include/osmocom/hnbgw/context_map.h M include/osmocom/hnbgw/hnbgw.h M include/osmocom/hnbgw/hnbgw_cn.h M src/osmo-hnbgw/context_map.c M src/osmo-hnbgw/context_map_sccp.c M src/osmo-hnbgw/hnbgw.c M src/osmo-hnbgw/hnbgw_cn.c M src/osmo-hnbgw/hnbgw_rua.c M src/osmo-hnbgw/hnbgw_vty.c M src/osmo-hnbgw/osmo_hnbgw_main.c M tests/config/defaults.vty M tests/config/one_cs7.vty M tests/config/one_cs7_with_addrs.vty M tests/config/one_cs7_with_iucs_addr.vty M tests/config/one_cs7_with_iups_addr.vty A tests/config/two_cs7.cfg A tests/config/two_cs7.vty A tests/config/two_cs7_with_addrs.cfg A tests/config/two_cs7_with_addrs.vty 20 files changed, 674 insertions(+), 298 deletions(-)
Approvals: Jenkins Builder: Verified neels: Looks good to me, approved
diff --git a/doc/charts/sccp.dot b/doc/charts/sccp.dot index 9c04c35..ed11ab9 100644 --- a/doc/charts/sccp.dot +++ b/doc/charts/sccp.dot @@ -9,29 +9,50 @@ ss0 -> ss0ab
msc0a [label="2.2.2"] - sgsn0a [label="3.3.3"] - ss0ab -> msc0a,sgsn0a + ss0ab -> msc0a }
- iucs_addr [label=".iucs_addr -> 2.2.2"] - iups_addr [label=".iups_addr -> 3.3.3"] - msc0a -> iucs_addr [dir=back] - sgsn0a -> iups_addr [dir=back] - cnlink [label="hnbgw_cnlink (singleton)\n .osmo_sccp_instance\n .osmo_ss7_user SSN: RANAP"]; - ss0 -> cnlink [dir=back] + sccp0 [label="hnbgw_sccp_user for '0'\n .osmo_ss7_instance 0\n .osmo_sccp_user SSN: RANAP\n PC: ss7 primary = 1.1.1"]; + ss0 -> sccp0 [dir=back] + + msc0 [label="hnbgw_cnlink for IuCS\n .remote_addr -> 2.2.2"] + sccp0 -> msc0 [dir=back] + msc0a -> msc0 [dir=back]
cs0 [label="UE CS conn\n hnbgw_context_map"] cs1 [label="UE CS conn\n hnbgw_context_map"] + msc0 -> cs0,cs1 + + subgraph cluster_ss1 { + label="" + ss1 [label="cs7 instance 1\n local pc: 4.4.4"] + ss1ab [label="address book"] + ss1 -> ss1ab + + sgsn0a [label="3.3.3"] + ss1ab -> sgsn0a + } + + sccp1 [label="hnbgw_sccp_user for '1'\n .osmo_ss7_instance 1\n .osmo_sccp_user SSN: RANAP\n PC: ss7 primary = 4.4.4"]; + ss1 -> sccp1 [dir=back] + + sgsn0 [label="hnbgw_cnlink for IuPS\n .remote_addr -> 3.3.3"] + sccp1 -> sgsn0 [dir=back] + sgsn0a -> sgsn0 [dir=back] + ps0 [label="UE PS conn\n hnbgw_context_map"] ps1 [label="UE PS conn\n hnbgw_context_map"] - cnlink -> cs0,cs1,ps0,ps1 - iucs_addr -> cs0,cs1 [style=dotted,dir=none] - iups_addr -> ps0,ps1 [style=dotted,dir=none] + sgsn0 -> ps0,ps1 + + subgraph cluster_sccp_inst { + label="global sccp.users (llist)" + sccp0 + sccp1 + }
subgraph cluster_hnbgw { - label="global hnb_gw" - cnlink - iucs_addr - iups_addr + label="global hnbgw" + msc0 + sgsn0 } } diff --git a/include/osmocom/hnbgw/context_map.h b/include/osmocom/hnbgw/context_map.h index 9320ce0..fe9d3e0 100644 --- a/include/osmocom/hnbgw/context_map.h +++ b/include/osmocom/hnbgw/context_map.h @@ -74,11 +74,14 @@
struct hnbgw_context_map { /* entry in the per-CN list of mappings */ - struct llist_head cn_list; + struct llist_head hnbgw_cnlink_entry; /* entry in the per-HNB list of mappings. If hnb_ctx == NULL, then this llist entry has been llist_del()eted and * must not be used. */ struct llist_head hnb_list;
+ /* entry in the per-SCCP-conn-id hashtable */ + struct hlist_node hnbgw_sccp_user_entry; + /* Pointer to HNB for this map, to transceive RUA. If the HNB has disconnected without releasing the RUA * context, this is NULL. */ struct hnb_context *hnb_ctx; @@ -88,7 +91,7 @@ struct osmo_fsm_inst *rua_fi;
/* Pointer to CN, to transceive SCCP. */ - struct hnbgw_cnlink *cn_link; + struct hnbgw_cnlink *cnlink; /* SCCP User SAP connection ID used in SCCP messages to/from the cn_link. */ uint32_t scu_conn_id; /* FSM handling the SCCP state for scu_conn_id. */ @@ -133,17 +136,12 @@ enum hnbgw_context_map_state map_rua_get_state(struct hnbgw_context_map *map); enum hnbgw_context_map_state map_sccp_get_state(struct hnbgw_context_map *map);
-struct hnbgw_context_map * -context_map_alloc_by_hnb(struct hnb_context *hnb, uint32_t rua_ctx_id, - bool is_ps, - struct hnbgw_cnlink *cn_if_new); +struct hnbgw_context_map *context_map_find_or_create_by_rua_ctx_id(struct hnb_context *hnb, uint32_t rua_ctx_id, + bool is_ps);
void map_rua_fsm_alloc(struct hnbgw_context_map *map); void map_sccp_fsm_alloc(struct hnbgw_context_map *map);
-struct hnbgw_context_map * -context_map_by_cn(struct hnbgw_cnlink *cn, uint32_t scu_conn_id); - void context_map_hnb_released(struct hnbgw_context_map *map);
#define map_rua_dispatch(MAP, EVENT, MSGB) \ diff --git a/include/osmocom/hnbgw/hnbgw.h b/include/osmocom/hnbgw/hnbgw.h index 6570bdf..7e6bda7 100644 --- a/include/osmocom/hnbgw/hnbgw.h +++ b/include/osmocom/hnbgw/hnbgw.h @@ -2,11 +2,14 @@
#include <osmocom/core/select.h> #include <osmocom/core/linuxlist.h> +#include <osmocom/core/hashtable.h> #include <osmocom/core/write_queue.h> #include <osmocom/core/timer.h> #include <osmocom/sigtran/sccp_sap.h> #include <osmocom/sigtran/osmo_ss7.h> #include <osmocom/ctrl/control_if.h> +#include <osmocom/ranap/RANAP_CN-DomainIndicator.h> + #define DEBUG #include <osmocom/core/logging.h>
@@ -29,6 +32,9 @@ #define LOGHNB(HNB_CTX, ss, lvl, fmt, args ...) \ LOGP(ss, lvl, "(%s) " fmt, hnb_context_name(HNB_CTX), ## args)
+#define DOMAIN_CS RANAP_CN_DomainIndicator_cs_domain +#define DOMAIN_PS RANAP_CN_DomainIndicator_ps_domain + enum hnb_ctrl_node { CTRL_NODE_HNB = _LAST_CTRL_NODE, _LAST_CTRL_NODE_HNB @@ -40,6 +46,10 @@ #define HNBGW_IUCS_REMOTE_IP_DEFAULT "127.0.0.1" #define HNBGW_IUPS_REMOTE_IP_DEFAULT "127.0.0.1"
+#define DEFAULT_PC_HNBGW ((23 << 3) + 5) +#define DEFAULT_PC_MSC ((23 << 3) + 1) +#define DEFAULT_PC_SGSN ((23 << 3) + 4) + /* 25.467 Section 7.1 */ #define IUH_DEFAULT_SCTP_PORT 29169 #define RNA_DEFAULT_SCTP_PORT 25471 @@ -61,17 +71,79 @@ uint32_t cid; /*!< Cell ID */ };
-struct hnbgw_cnlink { - struct llist_head list; +/* osmo-hnbgw keeps a single hnbgw_sccp_user per osmo_sccp_instance, for the local point-code and SSN == RANAP. + * This relates the (opaque) osmo_sccp_user to osmo-hnbgw's per-ss7 state. */ +struct hnbgw_sccp_user { + /* entry in g_hnbgw->sccp.users */ + struct llist_head entry;
- /* reference to the SCCP User SAP by which we communicate */ - struct osmo_sccp_instance *sccp; + /* logging context */ + char *name; + + /* Which 'cs7 instance' is this for? Below sccp_user is registered at the osmo_sccp_instance ss7->sccp. */ + struct osmo_ss7_instance *ss7; + + /* Local address: cs7 instance's primary PC if present, else the default HNBGW PC; with SSN == RANAP. */ + struct osmo_sccp_addr local_addr; + + /* osmo_sccp API state for above local address on above ss7 instance. */ struct osmo_sccp_user *sccp_user;
+ /* Fast access to the hnbgw_context_map responsible for a given SCCP conn_id of the ss7->sccp instance. + * hlist_node: hnbgw_context_map->hnbgw_sccp_user_entry. */ + DECLARE_HASHTABLE(hnbgw_context_map_by_conn_id, 6); +}; + +#define LOG_HSI(HNBGW_SCCP_INST, SUBSYS, LEVEL, FMT, ARGS...) \ + LOGP(SUBSYS, LEVEL, "(%s) " FMT, (HNBGW_SCCP_INST) ? (HNBGW_SCCP_INST)->name : "null", ##ARGS) + +/* A CN peer, like MSC or SGSN. */ +struct hnbgw_cnlink { + /* To print in logging/VTY */ + char *name; + + /* IuCS or IuPS? */ + RANAP_CN_DomainIndicator_t domain; + + /* cs7 address book entry to indicate both the remote point-code of the peer, as well as which cs7 instance to + * use. */ + const char *remote_addr_name; + + /* Copy of the address pointed at by remote_addr_name. */ + struct osmo_sccp_addr remote_addr; + + /* The SCCP instance for the cs7 instance indicated by remote_addr_name. (Multiple hnbgw_cnlinks may use the + * same hnbgw_sccp_user -- there is exactly one hnbgw_sccp_user per configured cs7 instance.) */ + struct hnbgw_sccp_user *hnbgw_sccp_user; + /* linked list of hnbgw_context_map */ struct llist_head map_list; };
+#define LOG_CNLINK(CNLINK, SUBSYS, LEVEL, FMT, ARGS...) \ + LOGP(SUBSYS, LEVEL, "(%s) " FMT, (CNLINK) ? (CNLINK)->name : "null", ##ARGS) + +static inline bool cnlink_is_cs(const struct hnbgw_cnlink *cnlink) +{ + return cnlink && cnlink->domain == DOMAIN_CS; +} + +static inline bool cnlink_is_ps(const struct hnbgw_cnlink *cnlink) +{ + return cnlink && cnlink->domain == DOMAIN_PS; +} + +static inline struct osmo_sccp_instance *cnlink_sccp(const struct hnbgw_cnlink *cnlink) +{ + if (!cnlink) + return NULL; + if (!cnlink->hnbgw_sccp_user) + return NULL; + if (!cnlink->hnbgw_sccp_user->ss7) + return NULL; + return cnlink->hnbgw_sccp_user->ss7->sccp; +} + /* The lifecycle of the hnb_context object is the same as its conn */ struct hnb_context { /*! Entry in HNB-global list of HNB */ @@ -139,11 +211,11 @@ struct ctrl_handle *ctrl; /* currently active CN links for CS and PS */ struct { - struct osmo_sccp_instance *client; - struct hnbgw_cnlink *cnlink; - struct osmo_sccp_addr local_addr; - struct osmo_sccp_addr iucs_remote_addr; - struct osmo_sccp_addr iups_remote_addr; + /* List of hnbgw_sccp_user */ + struct llist_head users; + /* FUTURE: cnlink_iucs, cnlink_iups will be replaced with llist cnpool. */ + struct hnbgw_cnlink *cnlink_iucs; + struct hnbgw_cnlink *cnlink_iups; } sccp; /* MGW pool, also includes the single MGCP client as fallback if no * pool is configured. */ diff --git a/include/osmocom/hnbgw/hnbgw_cn.h b/include/osmocom/hnbgw/hnbgw_cn.h index 5711c5e..a684c98 100644 --- a/include/osmocom/hnbgw/hnbgw_cn.h +++ b/include/osmocom/hnbgw/hnbgw_cn.h @@ -2,6 +2,12 @@
#include <osmocom/hnbgw/hnbgw.h>
-int hnbgw_cnlink_init(const char *stp_host, uint16_t stp_port, const char *local_ip); +struct hnbgw_cnlink *hnbgw_cnlink_alloc(const char *remote_addr_name, RANAP_CN_DomainIndicator_t domain);
const struct osmo_sccp_addr *hnbgw_cn_get_remote_addr(bool is_ps); + +struct hnbgw_cnlink *hnbgw_cnlink_find_by_addr(const struct hnbgw_sccp_user *hsu, + const struct osmo_sccp_addr *remote_addr); +struct hnbgw_cnlink *hnbgw_cnlink_select(bool is_ps); + +char *cnlink_sccp_addr_to_str(struct hnbgw_cnlink *cnlink, const struct osmo_sccp_addr *addr); diff --git a/src/osmo-hnbgw/context_map.c b/src/osmo-hnbgw/context_map.c index f8d0ecf..cdc526b 100644 --- a/src/osmo-hnbgw/context_map.c +++ b/src/osmo-hnbgw/context_map.c @@ -28,7 +28,7 @@
#include <osmocom/sigtran/sccp_helpers.h>
-#include <osmocom/hnbgw/hnbgw.h> +#include <osmocom/hnbgw/hnbgw_cn.h> #include <osmocom/hnbgw/context_map.h> #include <osmocom/hnbgw/mgw_fsm.h> #include <osmocom/hnbgw/ps_rab_ass_fsm.h> @@ -53,16 +53,16 @@ }
/* Map from a HNB + ContextID to the SCCP-side Connection ID */ -struct hnbgw_context_map * -context_map_alloc_by_hnb(struct hnb_context *hnb, uint32_t rua_ctx_id, - bool is_ps, - struct hnbgw_cnlink *cn_if_new) +struct hnbgw_context_map *context_map_find_or_create_by_rua_ctx_id(struct hnb_context *hnb, uint32_t rua_ctx_id, + bool is_ps) { struct hnbgw_context_map *map; uint32_t new_scu_conn_id; + struct hnbgw_cnlink *cnlink; + struct hnbgw_sccp_user *hsu;
llist_for_each_entry(map, &hnb->map_list, hnb_list) { - if (map->cn_link != cn_if_new) + if (map->is_ps != is_ps) continue;
/* Matching on RUA context id -- only match for RUA context that has not been disconnected yet. If an @@ -71,24 +71,39 @@ if (!map_rua_is_active(map)) continue;
- if (map->rua_ctx_id == rua_ctx_id - && map->is_ps == is_ps) { - return map; - } + if (map->rua_ctx_id != rua_ctx_id) + continue; + + /* Already exists */ + return map; }
- new_scu_conn_id = osmo_sccp_instance_next_conn_id(map->cn_link->sccp); - if (new_scu_conn_id < 0) { - LOGHNB(hnb, DMAIN, LOGL_ERROR, "Unable to allocate CN connection ID\n"); + /* Does not exist yet, create a new hnbgw_context_map. */ + + /* From the RANAP/RUA input, determine which cnlink to use */ + cnlink = hnbgw_cnlink_select(is_ps); + if (!cnlink) { + LOGHNB(hnb, DMAIN, LOGL_ERROR, "Failed to select CN link\n"); return NULL; }
- LOGHNB(hnb, DMAIN, LOGL_INFO, "Creating new Mapping RUA CTX %p/%u <-> SCU Conn ID %p/%u\n", - hnb, rua_ctx_id, cn_if_new, new_scu_conn_id); + /* Allocate new SCCP conn id on the SCCP instance the cnlink is on. */ + hsu = cnlink->hnbgw_sccp_user; + if (!hsu) { + LOGHNB(hnb, DMAIN, LOGL_ERROR, "Cannot allocate context map: No SCCP instance for CN link %s\n", + cnlink->name); + return NULL; + } + + new_scu_conn_id = osmo_sccp_instance_next_conn_id(hsu->ss7->sccp); + if (new_scu_conn_id < 0) { + LOGHNB(hnb, DMAIN, LOGL_ERROR, "Unable to allocate SCCP conn ID on %s\n", hsu->name); + return NULL; + }
/* allocate a new map entry. */ map = talloc_zero(hnb, struct hnbgw_context_map); - map->cn_link = cn_if_new; + map->cnlink = cnlink; map->hnb_ctx = hnb; map->rua_ctx_id = rua_ctx_id; map->is_ps = is_ps; @@ -99,9 +114,12 @@ map_rua_fsm_alloc(map); map_sccp_fsm_alloc(map);
- /* put it into both lists */ llist_add_tail(&map->hnb_list, &hnb->map_list); - llist_add_tail(&map->cn_list, &cn_if_new->map_list); + llist_add_tail(&map->hnbgw_cnlink_entry, &cnlink->map_list); + hash_add(hsu->hnbgw_context_map_by_conn_id, &map->hnbgw_sccp_user_entry, new_scu_conn_id); + + LOG_MAP(map, DMAIN, LOGL_INFO, "Creating new Mapping RUA CTX %u <-> SCU Conn ID %s/%u\n", + rua_ctx_id, hsu->name, new_scu_conn_id);
return map; } @@ -133,30 +151,6 @@ return msg && msgb_l2(msg) ? msgb_l2len(msg) : 0; }
-/* Map from a CN + Connection ID to HNB + Context ID */ -struct hnbgw_context_map * -context_map_by_cn(struct hnbgw_cnlink *cn, uint32_t scu_conn_id) -{ - struct hnbgw_context_map *map; - - llist_for_each_entry(map, &cn->map_list, cn_list) { - /* Matching on SCCP conn id -- only match for SCCP conn that has not been disconnected yet. If an - * inactive context map for an scu_conn_id is still around, we may have two entries for the same - * scu_conn_id around at the same time. That should only stay until its RUA side is done releasing. */ - if (!map_sccp_is_active(map)) - continue; - - if (map->scu_conn_id == scu_conn_id) { - return map; - } - } - /* we don't allocate new mappings in the CN->HNB - * direction, as the RUA=SCCP=SUA connections are always - * established from HNB towards CN. */ - LOGP(DMAIN, LOGL_NOTICE, "Unable to resolve map for CN " "connection ID %p/%u\n", cn, scu_conn_id); - return NULL; -} - void context_map_hnb_released(struct hnbgw_context_map *map) { /* When a HNB disconnects from RUA, the hnb_context will be freed. This hnbgw_context_map was allocated as a @@ -199,8 +193,10 @@ hnbgw_gtpmap_release(map); #endif
- if (map->cn_link) - llist_del(&map->cn_list); + if (map->cnlink) { + llist_del(&map->hnbgw_cnlink_entry); + hash_del(&map->hnbgw_sccp_user_entry); + } if (map->hnb_ctx) llist_del(&map->hnb_list);
diff --git a/src/osmo-hnbgw/context_map_sccp.c b/src/osmo-hnbgw/context_map_sccp.c index 3de8215..00b24f2 100644 --- a/src/osmo-hnbgw/context_map_sccp.c +++ b/src/osmo-hnbgw/context_map_sccp.c @@ -124,6 +124,11 @@ struct osmo_scu_prim *prim; int rc;
+ if (!map->cnlink || !map->cnlink->hnbgw_sccp_user) { + LOGPFSML(fi, LOGL_ERROR, "Failed to send SCCP Connection Request: no CN link\n"); + return -1; + } + if (!ranap_msg) { /* prepare a msgb to send an empty N-Connect prim (but this should never happen in practice) */ ranap_msg = hnbgw_ranap_msg_alloc("SCCP-CR-empty"); @@ -132,13 +137,13 @@ prim = (struct osmo_scu_prim *)msgb_push(ranap_msg, sizeof(*prim)); osmo_prim_init(&prim->oph, SCCP_SAP_USER, OSMO_SCU_PRIM_N_CONNECT, PRIM_OP_REQUEST, ranap_msg); prim->u.connect.called_addr = *hnbgw_cn_get_remote_addr(map->is_ps); - prim->u.connect.calling_addr = g_hnbgw->sccp.local_addr; + prim->u.connect.calling_addr = map->cnlink->hnbgw_sccp_user->local_addr; prim->u.connect.sccp_class = 2; prim->u.connect.conn_id = map->scu_conn_id;
- rc = osmo_sccp_user_sap_down_nofree(map->cn_link->sccp_user, &prim->oph); + rc = osmo_sccp_user_sap_down_nofree(map->cnlink->hnbgw_sccp_user->sccp_user, &prim->oph); if (rc) - LOGPFSML(fi, LOGL_ERROR, "Failed to forward SCCP Connectoin Request to CN\n"); + LOGPFSML(fi, LOGL_ERROR, "Failed to send SCCP Connection Request to CN\n"); return rc; }
@@ -151,20 +156,31 @@ if (!msg_has_l2_data(ranap_msg)) return 0;
+ if (!map->cnlink || !map->cnlink->hnbgw_sccp_user) { + LOGPFSML(fi, LOGL_ERROR, "Failed to send SCCP Data Form 1: no CN link\n"); + return -1; + } + prim = (struct osmo_scu_prim *)msgb_push(ranap_msg, sizeof(*prim)); osmo_prim_init(&prim->oph, SCCP_SAP_USER, OSMO_SCU_PRIM_N_DATA, PRIM_OP_REQUEST, ranap_msg); prim->u.data.conn_id = map->scu_conn_id;
- rc = osmo_sccp_user_sap_down_nofree(map->cn_link->sccp_user, &prim->oph); + rc = osmo_sccp_user_sap_down_nofree(map->cnlink->hnbgw_sccp_user->sccp_user, &prim->oph); if (rc) - LOGPFSML(fi, LOGL_ERROR, "Failed to forward SCCP Data Form 1 to CN\n"); + LOGPFSML(fi, LOGL_ERROR, "Failed to send SCCP Data Form 1 to CN\n"); return rc; }
static int tx_sccp_rlsd(struct osmo_fsm_inst *fi) { struct hnbgw_context_map *map = fi->priv; - return osmo_sccp_tx_disconn(map->cn_link->sccp_user, map->scu_conn_id, NULL, 0); + + if (!map->cnlink || !map->cnlink->hnbgw_sccp_user) { + LOGPFSML(fi, LOGL_ERROR, "Failed to send SCCP RLSD: no CN link\n"); + return -1; + } + + return osmo_sccp_tx_disconn(map->cnlink->hnbgw_sccp_user->sccp_user, map->scu_conn_id, NULL, 0); }
static int destruct_ranap_ran_rx_co_ies(ranap_message *ranap_message_p) @@ -468,7 +484,7 @@ /* send SCCP RLSD. libosmo-sigtran/sccp_scoc.c will do the SCCP connection cleanup. * (It will repeatedly send SCCP RLSD until the peer responded with SCCP RLC, or until the * sccp_connection->t_int timer expires, and the sccp_connection is freed.) */ - if (map->cn_link && map->cn_link->sccp_user) + if (map->cnlink) tx_sccp_rlsd(fi); map_sccp_fsm_state_chg(MAP_SCCP_ST_DISCONNECTED); return 0; diff --git a/src/osmo-hnbgw/hnbgw.c b/src/osmo-hnbgw/hnbgw.c index 6bf7b3f..b07dbc7 100644 --- a/src/osmo-hnbgw/hnbgw.c +++ b/src/osmo-hnbgw/hnbgw.c @@ -51,6 +51,7 @@ g_hnbgw->next_ue_ctx_id = 23; INIT_LLIST_HEAD(&g_hnbgw->hnb_list); INIT_LLIST_HEAD(&g_hnbgw->ue_list); + INIT_LLIST_HEAD(&g_hnbgw->sccp.users);
g_hnbgw->mgw_pool = mgcp_client_pool_alloc(g_hnbgw); g_hnbgw->config.mgcp_client = talloc_zero(g_hnbgw, struct mgcp_client_conf); diff --git a/src/osmo-hnbgw/hnbgw_cn.c b/src/osmo-hnbgw/hnbgw_cn.c index 33ec0f6..0175498 100644 --- a/src/osmo-hnbgw/hnbgw_cn.c +++ b/src/osmo-hnbgw/hnbgw_cn.c @@ -33,6 +33,7 @@
#include <osmocom/hnbgw/hnbgw.h> #include <osmocom/hnbgw/hnbgw_rua.h> +#include <osmocom/hnbgw/hnbgw_cn.h> #include <osmocom/ranap/ranap_ies_defs.h> #include <osmocom/ranap/ranap_msg_factory.h> #include <osmocom/hnbgw/context_map.h> @@ -47,33 +48,47 @@ .choice. transmissionNetwork = RANAP_CauseTransmissionNetwork_signalling_transport_resource_failure, };
- LOGP(DRANAP, LOGL_NOTICE, "Tx RESET to %s %s\n", - domain == RANAP_CN_DomainIndicator_cs_domain ? "IuCS" : "IuPS", - osmo_sccp_inst_addr_name(g_hnbgw->sccp.cnlink->sccp, remote_addr)); + if (!cnlink) + return -1;
- msg = ranap_new_msg_reset(domain, &cause); + if (!cnlink->hnbgw_sccp_user) { + LOG_CNLINK(cnlink, DRANAP, LOGL_ERROR, "cannot send RANAP RESET: no CN link\n"); + return -1; + }
- return osmo_sccp_tx_unitdata_msg(g_hnbgw->sccp.cnlink->sccp_user, - &g_hnbgw->sccp.local_addr, - remote_addr, + LOG_CNLINK(cnlink, DRANAP, LOGL_NOTICE, "Tx RANAP RESET to %s %s\n", + cnlink_is_cs(cnlink) ? "IuCS" : "IuPS", + osmo_sccp_inst_addr_name(cnlink->hnbgw_sccp_user->sccp, &cnlink->remote_addr)); + + msg = ranap_new_msg_reset(cnlink->domain, &cause); + + return osmo_sccp_tx_unitdata_msg(cnlink->hnbgw_sccp_user->sccp_user, + &cnlink->local_addr, + &cnlink->remote_addr, msg); } #endif
-static int transmit_reset_ack(RANAP_CN_DomainIndicator_t domain, - const struct osmo_sccp_addr *remote_addr) +static int transmit_reset_ack(struct hnbgw_cnlink *cnlink) { struct msgb *msg; + struct osmo_sccp_instance *sccp = cnlink_sccp(cnlink);
- LOGP(DRANAP, LOGL_NOTICE, "Tx RESET ACK to %s %s\n", - domain == RANAP_CN_DomainIndicator_cs_domain ? "IuCS" : "IuPS", - osmo_sccp_inst_addr_name(g_hnbgw->sccp.cnlink->sccp, remote_addr)); + if (!sccp) { + LOG_CNLINK(cnlink, DRANAP, LOGL_ERROR, "cannot send RANAP RESET ACK: no CN link\n"); + return -1; + }
- msg = ranap_new_msg_reset_ack(domain, NULL); + LOG_CNLINK(cnlink, DRANAP, LOGL_NOTICE, "Tx RANAP RESET ACK %s %s --> %s\n", + cnlink_is_cs(cnlink) ? "IuCS" : "IuPS", + cnlink_sccp_addr_to_str(cnlink, &cnlink->hnbgw_sccp_user->local_addr), + cnlink_sccp_addr_to_str(cnlink, &cnlink->remote_addr));
- return osmo_sccp_tx_unitdata_msg(g_hnbgw->sccp.cnlink->sccp_user, - &g_hnbgw->sccp.local_addr, - remote_addr, + msg = ranap_new_msg_reset_ack(cnlink->domain, NULL); + + return osmo_sccp_tx_unitdata_msg(cnlink->hnbgw_sccp_user->sccp_user, + &cnlink->hnbgw_sccp_user->local_addr, + &cnlink->remote_addr, msg); }
@@ -93,16 +108,16 @@ domain = ies.cN_DomainIndicator; ranap_free_reseties(&ies);
- LOGP(DRANAP, LOGL_NOTICE, "Rx RESET from %s %s, returning ACK\n", - domain == RANAP_CN_DomainIndicator_cs_domain ? "IuCS" : "IuPS", - osmo_sccp_inst_addr_name(cnlink->sccp, &unitdata->calling_addr)); + LOG_CNLINK(cnlink, DRANAP, LOGL_NOTICE, "Rx RESET from %s %s, returning ACK\n", + domain == DOMAIN_CS ? "IuCS" : "IuPS", + osmo_sccp_inst_addr_name(cnlink_sccp(cnlink), &unitdata->calling_addr));
/* FIXME: actually reset connections, if any */
- if (transmit_reset_ack(domain, &unitdata->calling_addr)) + if (transmit_reset_ack(cnlink)) LOGP(DRANAP, LOGL_ERROR, "Error: cannot send RESET ACK to %s %s\n", - domain == RANAP_CN_DomainIndicator_cs_domain ? "IuCS" : "IuPS", - osmo_sccp_inst_addr_name(cnlink->sccp, &unitdata->calling_addr)); + domain == DOMAIN_CS ? "IuCS" : "IuPS", + osmo_sccp_inst_addr_name(cnlink_sccp(cnlink), &unitdata->calling_addr));
return rc; } @@ -246,101 +261,94 @@ return rc; }
-static bool pc_and_ssn_match(const struct osmo_sccp_addr *a, const struct osmo_sccp_addr *b) +static struct hnbgw_cnlink *cnlink_from_addr(struct hnbgw_sccp_user *hsu, const struct osmo_sccp_addr *calling_addr, + const struct osmo_prim_hdr *oph) { - return (a == b) - || ((a->pc == b->pc) - && (a->ssn == b->ssn)); + struct hnbgw_cnlink *cnlink = NULL; + cnlink = hnbgw_cnlink_find_by_addr(hsu, calling_addr); + if (!cnlink) { + LOG_HSI(hsu, DRANAP, LOGL_ERROR, "Rx from unknown SCCP peer: %s: %s\n", + osmo_sccp_inst_addr_name(hsu->ss7->sccp, calling_addr), + osmo_scu_prim_hdr_name_c(OTC_SELECT, oph)); + return NULL; + } + return cnlink; }
-static int classify_cn_remote_addr(const struct osmo_sccp_addr *cn_remote_addr, - bool *is_ps) +static struct hnbgw_context_map *map_from_conn_id(struct hnbgw_sccp_user *hsu, uint32_t conn_id, + const struct osmo_prim_hdr *oph) { - if (pc_and_ssn_match(cn_remote_addr, &g_hnbgw->sccp.iucs_remote_addr)) { - if (is_ps) - *is_ps = false; - return 0; - } - if (pc_and_ssn_match(cn_remote_addr, &g_hnbgw->sccp.iups_remote_addr)) { - if (is_ps) - *is_ps = true; - return 0; - } - LOGP(DMAIN, LOGL_ERROR, "Unexpected remote address, matches neither CS nor PS address: %s\n", - osmo_sccp_addr_dump(cn_remote_addr)); - return -1; + struct hnbgw_context_map *map; + hash_for_each_possible(hsu->hnbgw_context_map_by_conn_id, map, hnbgw_sccp_user_entry, conn_id) + return map; + LOGP(DRANAP, LOGL_ERROR, "Rx for unknown SCCP connection ID: %u: %s\n", + conn_id, osmo_scu_prim_hdr_name_c(OTC_SELECT, oph)); + return NULL; }
-static int handle_cn_unitdata(struct hnbgw_cnlink *cnlink, +static int handle_cn_unitdata(struct hnbgw_sccp_user *hsu, const struct osmo_scu_unitdata_param *param, struct osmo_prim_hdr *oph) { + struct hnbgw_cnlink *cnlink = cnlink_from_addr(hsu, ¶m->calling_addr, oph); + if (!cnlink) + return -ENOENT; + if (param->called_addr.ssn != OSMO_SCCP_SSN_RANAP) { LOGP(DMAIN, LOGL_NOTICE, "N-UNITDATA.ind for unknown SSN %u\n", param->called_addr.ssn); return -1; }
- if (classify_cn_remote_addr(¶m->calling_addr, NULL) < 0) - return -1; - return handle_cn_ranap(cnlink, param, msgb_l2(oph->msg), msgb_l2len(oph->msg)); }
-static int handle_cn_conn_conf(struct hnbgw_cnlink *cnlink, +static int handle_cn_conn_conf(struct hnbgw_sccp_user *hsu, const struct osmo_scu_connect_param *param, struct osmo_prim_hdr *oph) { - struct osmo_ss7_instance *ss7 = osmo_sccp_get_ss7(g_hnbgw->sccp.client); struct hnbgw_context_map *map;
+ map = map_from_conn_id(hsu, param->conn_id, oph); + if (!map || !map->cnlink) + return -ENOENT; + LOGP(DMAIN, LOGL_DEBUG, "handle_cn_conn_conf() conn_id=%d, addrs: called=%s calling=%s responding=%s\n", param->conn_id, - osmo_sccp_addr_to_str_c(OTC_SELECT, ss7, ¶m->called_addr), - osmo_sccp_addr_to_str_c(OTC_SELECT, ss7, ¶m->calling_addr), - osmo_sccp_addr_to_str_c(OTC_SELECT, ss7, ¶m->responding_addr)); - - map = context_map_by_cn(cnlink, param->conn_id); - if (!map) { - /* We have no such SCCP connection. Ignore. */ - return 0; - } + cnlink_sccp_addr_to_str(map->cnlink, ¶m->called_addr), + cnlink_sccp_addr_to_str(map->cnlink, ¶m->calling_addr), + cnlink_sccp_addr_to_str(map->cnlink, ¶m->responding_addr));
map_sccp_dispatch(map, MAP_SCCP_EV_RX_CONNECTION_CONFIRM, oph->msg); return 0; }
-static int handle_cn_data_ind(struct hnbgw_cnlink *cnlink, +static int handle_cn_data_ind(struct hnbgw_sccp_user *hsu, const struct osmo_scu_data_param *param, struct osmo_prim_hdr *oph) { struct hnbgw_context_map *map;
- map = context_map_by_cn(cnlink, param->conn_id); - if (!map) { - /* We have no such SCCP connection. Ignore. */ - return 0; - } + map = map_from_conn_id(hsu, param->conn_id, oph); + if (!map || !map->cnlink) + return -ENOENT;
return map_sccp_dispatch(map, MAP_SCCP_EV_RX_DATA_INDICATION, oph->msg); }
-static int handle_cn_disc_ind(struct hnbgw_cnlink *cnlink, +static int handle_cn_disc_ind(struct hnbgw_sccp_user *hsu, const struct osmo_scu_disconn_param *param, struct osmo_prim_hdr *oph) { struct hnbgw_context_map *map;
- LOGP(DMAIN, LOGL_DEBUG, "handle_cn_disc_ind() conn_id=%d originator=%d\n", - param->conn_id, param->originator); - LOGP(DMAIN, LOGL_DEBUG, "handle_cn_disc_ind() responding_addr=%s\n", - inet_ntoa(param->responding_addr.ip.v4)); + map = map_from_conn_id(hsu, param->conn_id, oph); + if (!map || !map->cnlink) + return -ENOENT;
- map = context_map_by_cn(cnlink, param->conn_id); - if (!map) { - /* We have no connection. Ignore. */ - return 0; - } + LOGP(DMAIN, LOGL_DEBUG, "handle_cn_disc_ind() conn_id=%u responding_addr=%s\n", + param->conn_id, + cnlink_sccp_addr_to_str(map->cnlink, ¶m->responding_addr));
return map_sccp_dispatch(map, MAP_SCCP_EV_RX_RELEASED, oph->msg); } @@ -349,7 +357,7 @@ static int sccp_sap_up(struct osmo_prim_hdr *oph, void *ctx) { struct osmo_sccp_user *scu = ctx; - struct hnbgw_cnlink *cnlink; + struct hnbgw_sccp_user *hsu; struct osmo_scu_prim *prim = (struct osmo_scu_prim *) oph; int rc = 0;
@@ -362,10 +370,10 @@ return -1; }
- cnlink = osmo_sccp_user_get_priv(scu); - if (!cnlink) { + hsu = osmo_sccp_user_get_priv(scu); + if (!hsu) { LOGP(DMAIN, LOGL_ERROR, - "sccp_sap_up(): NULL hnbgw_cnlink, cannot send prim (sap %u prim %u op %d)\n", + "sccp_sap_up(): NULL hnbgw_sccp_user, cannot send prim (sap %u prim %u op %d)\n", oph->sap, oph->primitive, oph->operation); return -1; } @@ -374,16 +382,16 @@
switch (OSMO_PRIM_HDR(oph)) { case OSMO_PRIM(OSMO_SCU_PRIM_N_UNITDATA, PRIM_OP_INDICATION): - rc = handle_cn_unitdata(cnlink, &prim->u.unitdata, oph); + rc = handle_cn_unitdata(hsu, &prim->u.unitdata, oph); break; case OSMO_PRIM(OSMO_SCU_PRIM_N_CONNECT, PRIM_OP_CONFIRM): - rc = handle_cn_conn_conf(cnlink, &prim->u.connect, oph); + rc = handle_cn_conn_conf(hsu, &prim->u.connect, oph); break; case OSMO_PRIM(OSMO_SCU_PRIM_N_DATA, PRIM_OP_INDICATION): - rc = handle_cn_data_ind(cnlink, &prim->u.data, oph); + rc = handle_cn_data_ind(hsu, &prim->u.data, oph); break; case OSMO_PRIM(OSMO_SCU_PRIM_N_DISCONNECT, PRIM_OP_INDICATION): - rc = handle_cn_disc_ind(cnlink, &prim->u.disconnect, oph); + rc = handle_cn_disc_ind(hsu, &prim->u.disconnect, oph); break; case OSMO_PRIM(OSMO_SCU_PRIM_N_PCSTATE, PRIM_OP_INDICATION): LOGP(DMAIN, LOGL_DEBUG, "Ignoring prim %s from SCCP USER SAP\n", @@ -412,8 +420,6 @@ const char *addr_name, const char *label, uint32_t default_pc) { - struct osmo_ss7_instance *ss7_tmp; - if (!addr_name) { osmo_sccp_make_addr_pc_ssn(dest, default_pc, OSMO_SCCP_SSN_RANAP); LOGP(DMAIN, LOGL_INFO, "%s remote addr not configured, using default: %s\n", label, @@ -421,21 +427,13 @@ return 0; }
- ss7_tmp = osmo_sccp_addr_by_name(dest, addr_name); - if (!ss7_tmp) { + *ss7 = osmo_sccp_addr_by_name(dest, addr_name); + if (!*ss7) { LOGP(DMAIN, LOGL_ERROR, "%s remote addr: no such SCCP address book entry: '%s'\n", - label, addr_name); + label, addr_name); return -1; }
- if (*ss7 && (*ss7 != ss7_tmp)) { - LOGP(DMAIN, LOGL_ERROR, "IuCS and IuPS cannot be served from separate CS7 instances," - " cs7 instance %d != %d\n", (*ss7)->cfg.id, ss7_tmp->cfg.id); - return -1; - } - - *ss7 = ss7_tmp; - osmo_sccp_addr_set_ssn(dest, OSMO_SCCP_SSN_RANAP);
if (!addr_has_pc_and_ssn(dest)) { @@ -449,74 +447,197 @@ return 0; }
-int hnbgw_cnlink_init(const char *stp_host, uint16_t stp_port, const char *local_ip) +/* If not present yet, set up all of osmo_ss7_instance, osmo_sccp_instance and hnbgw_sccp_user for the given cnlink. + * The cs7 instance nr to use is determined by cnlink->remote_addr_name, or cs7 instance 0 if that is not present. + * Set cnlink->hnbgw_sccp_user to the new SCCP instance. Return 0 on success, negative on error. */ +int cnlink_ensure_sccp(struct hnbgw_cnlink *cnlink) { - struct hnbgw_cnlink *cnlink; - struct osmo_ss7_instance *ss7; + struct osmo_ss7_instance *ss7 = NULL; + struct osmo_sccp_instance *sccp; + struct osmo_sccp_user *sccp_user; uint32_t local_pc; + struct hnbgw_sccp_user *hsu;
- OSMO_ASSERT(!g_hnbgw->sccp.client); - OSMO_ASSERT(!g_hnbgw->sccp.cnlink); + /* If a hnbgw_sccp_user has already been set up, use that. */ + if (cnlink->hnbgw_sccp_user) { + LOG_CNLINK(cnlink, DCN, LOGL_DEBUG, "SCCP instance already set up, using %s\n", + cnlink->hnbgw_sccp_user->name); + return 0; + } + LOG_CNLINK(cnlink, DCN, LOGL_DEBUG, "no SCCP instance selected yet\n");
- ss7 = NULL; - if (resolve_addr_name(&g_hnbgw->sccp.iucs_remote_addr, &ss7, - g_hnbgw->config.iucs_remote_addr_name, "IuCS", (23 << 3) + 1)) - return -1; - if (resolve_addr_name(&g_hnbgw->sccp.iups_remote_addr, &ss7, - g_hnbgw->config.iups_remote_addr_name, "IuPS", (23 << 3) + 4)) - return -1; + /* Figure out which cs7 instance to use. If cnlink->remote_addr_name is set, it points to an address book entry + * in a specific cs7 instance. If it is not set, leave ss7 == NULL to use cs7 instance 0. */ + if (cnlink->remote_addr_name) { + LOG_CNLINK(cnlink, DCN, LOGL_DEBUG, "resolving 'remote-addr %s'\n", cnlink->remote_addr_name); + if (resolve_addr_name(&cnlink->remote_addr, &ss7, cnlink->remote_addr_name, cnlink->name, + DEFAULT_PC_HNBGW)) { + LOG_CNLINK(cnlink, DCN, LOGL_ERROR, "cannot initialize SCCP: there is no SCCP address named '%s'\n", + cnlink->remote_addr_name); + return -ENOENT; + }
+ LOG_CNLINK(cnlink, DCN, LOGL_DEBUG, "remote-addr is '%s', using cs7 instance %u\n", + cnlink->remote_addr_name, ss7->cfg.id); + } else { + /* If no address is configured, use the default remote CN address, according to legacy behavior. */ + uint32_t remote_pc; + switch (cnlink->domain) { + case DOMAIN_CS: + remote_pc = DEFAULT_PC_MSC; + break; + case DOMAIN_PS: + remote_pc = DEFAULT_PC_SGSN; + break; + default: + return -EINVAL; + } + osmo_sccp_make_addr_pc_ssn(&cnlink->remote_addr, remote_pc, OSMO_SCCP_SSN_RANAP); + } + + /* If no 'cs7 instance' has been selected by the address, see if there already is a cs7 0 we can use by default. + * If it doesn't exist, it will get created by osmo_sccp_simple_client_on_ss7_id(). */ if (!ss7) { - LOGP(DRANAP, LOGL_NOTICE, "No cs7 instance configured for IuCS nor IuPS," - " creating default instance\n"); - ss7 = osmo_ss7_instance_find_or_create(g_hnbgw, 0); - if (!ss7) - return -1; - ss7->cfg.primary_pc = (23 << 3) + 5; + ss7 = osmo_ss7_instance_find(0); + LOG_CNLINK(cnlink, DCN, LOGL_DEBUG, "Using default 'cs7 instance 0' (%s)\n", ss7 ? "already exists" : "will create"); }
- if (!osmo_ss7_pc_is_valid(ss7->cfg.primary_pc)) { - LOGP(DMAIN, LOGL_ERROR, "IuCS/IuPS uplink cannot be setup: CS7 instance %d has no point-code set\n", - ss7->cfg.id); + if (ss7) { + /* Has another cnlink already set up an SCCP instance for this ss7? */ + llist_for_each_entry(hsu, &g_hnbgw->sccp.users, entry) { + if (hsu->ss7 != ss7) + continue; + cnlink->hnbgw_sccp_user = hsu; + LOG_CNLINK(cnlink, DCN, LOGL_NOTICE, "using existing SCCP instance %s on cs7 instance %u\n", + hsu->name, ss7->cfg.id); + return 0; + } + /* else cnlink->hnbgw_sccp_user stays NULL and is set up below. */ + LOG_CNLINK(cnlink, DCN, LOGL_DEBUG, "cs7 instance %u has no SCCP instance yet\n", ss7->cfg.id); + + /* All SCCP instances should originate from this function. So if there is no hnbgw_sccp_user for the cs7 + * instance, then the cs7 instance should not have an SCCP instance yet. */ + OSMO_ASSERT(!ss7->sccp); + } + + /* No SCCP instance yet for this ss7. Create it. If no address name is given that resolves to a + * particular cs7 instance above, use 'cs7 instance 0'. */ + sccp = osmo_sccp_simple_client_on_ss7_id(g_hnbgw, ss7 ? ss7->cfg.id : 0, cnlink->name, DEFAULT_PC_HNBGW, + OSMO_SS7_ASP_PROT_M3UA, 0, "localhost", -1, "localhost"); + if (!sccp) { + LOG_CNLINK(cnlink, DCN, LOGL_ERROR, "Failed to configure 'cs7 instance %u'\n", ss7->cfg.id); return -1; } - local_pc = ss7->cfg.primary_pc; + ss7 = osmo_sccp_get_ss7(sccp); + LOG_CNLINK(cnlink, DCN, LOGL_NOTICE, "created SCCP instance on cs7 instance %u\n", ss7->cfg.id);
- osmo_sccp_make_addr_pc_ssn(&g_hnbgw->sccp.local_addr, local_pc, OSMO_SCCP_SSN_RANAP); - LOGP(DRANAP, LOGL_NOTICE, "Local SCCP addr: %s\n", osmo_sccp_addr_name(ss7, &g_hnbgw->sccp.local_addr)); + /* Bind the SCCP user, using the cs7 instance's default point-code if one is configured, or osmo-hnbgw's default + * local PC. */ + if (osmo_ss7_pc_is_valid(ss7->cfg.primary_pc)) + local_pc = ss7->cfg.primary_pc; + else + local_pc = DEFAULT_PC_HNBGW;
- g_hnbgw->sccp.client = osmo_sccp_simple_client_on_ss7_id(g_hnbgw, ss7->cfg.id, "OsmoHNBGW", - local_pc, OSMO_SS7_ASP_PROT_M3UA, - 0, local_ip, stp_port, stp_host); - if (!g_hnbgw->sccp.client) { - LOGP(DMAIN, LOGL_ERROR, "Failed to init SCCP Client\n"); - return -1; - } + LOG_CNLINK(cnlink, DCN, LOGL_DEBUG, "binding OsmoHNBGW user to cs7 instance %u, local PC %u = %s\n", + ss7->cfg.id, local_pc, osmo_ss7_pointcode_print(ss7, local_pc));
- cnlink = talloc_zero(g_hnbgw, struct hnbgw_cnlink); - INIT_LLIST_HEAD(&cnlink->map_list); - - cnlink->sccp_user = osmo_sccp_user_bind_pc(g_hnbgw->sccp.client, "OsmoHNBGW", sccp_sap_up, - OSMO_SCCP_SSN_RANAP, g_hnbgw->sccp.local_addr.pc); - if (!cnlink->sccp_user) { + sccp_user = osmo_sccp_user_bind_pc(sccp, "OsmoHNBGW", sccp_sap_up, OSMO_SCCP_SSN_RANAP, local_pc); + if (!sccp_user) { LOGP(DMAIN, LOGL_ERROR, "Failed to init SCCP User\n"); return -1; }
- LOGP(DRANAP, LOGL_NOTICE, "Remote SCCP addr: IuCS: %s\n", - osmo_sccp_addr_name(ss7, &g_hnbgw->sccp.iucs_remote_addr)); - LOGP(DRANAP, LOGL_NOTICE, "Remote SCCP addr: IuPS: %s\n", - osmo_sccp_addr_name(ss7, &g_hnbgw->sccp.iups_remote_addr)); + hsu = talloc_zero(cnlink, struct hnbgw_sccp_user); + *hsu = (struct hnbgw_sccp_user){ + .name = talloc_asprintf(hsu, "cs7-%u.sccp", ss7->cfg.id), + .ss7 = ss7, + .sccp_user = sccp_user, + }; + osmo_sccp_make_addr_pc_ssn(&hsu->local_addr, local_pc, OSMO_SCCP_SSN_RANAP); + hash_init(hsu->hnbgw_context_map_by_conn_id); + osmo_sccp_user_set_priv(sccp_user, hsu);
- /* In sccp_sap_up() we expect the cnlink in the user's priv. */ - osmo_sccp_user_set_priv(cnlink->sccp_user, cnlink); + llist_add_tail(&hsu->entry, &g_hnbgw->sccp.users);
- g_hnbgw->sccp.cnlink = cnlink; - + cnlink->hnbgw_sccp_user = hsu; return 0; }
+struct hnbgw_cnlink *hnbgw_cnlink_alloc(const char *remote_addr_name, RANAP_CN_DomainIndicator_t domain) +{ + struct hnbgw_cnlink *cnlink; + + cnlink = talloc_zero(g_hnbgw, struct hnbgw_cnlink); + *cnlink = (struct hnbgw_cnlink){ + .name = (domain == DOMAIN_CS ? "msc-0" : "sgsn-0"), + .domain = domain, + .remote_addr_name = talloc_strdup(cnlink, remote_addr_name), + }; + + INIT_LLIST_HEAD(&cnlink->map_list); + + if (cnlink_ensure_sccp(cnlink)) { + /* error logging already in cnlink_ensure_sccp() */ + talloc_free(cnlink); + return NULL; + } + + switch (domain) { + case DOMAIN_CS: + OSMO_ASSERT(!g_hnbgw->sccp.cnlink_iucs); + g_hnbgw->sccp.cnlink_iucs = cnlink; + break; + case DOMAIN_PS: + OSMO_ASSERT(!g_hnbgw->sccp.cnlink_iups); + g_hnbgw->sccp.cnlink_iups = cnlink; + break; + default: + OSMO_ASSERT(false); + } + + return cnlink; +} + const struct osmo_sccp_addr *hnbgw_cn_get_remote_addr(bool is_ps) { - return is_ps ? &g_hnbgw->sccp.iups_remote_addr : &g_hnbgw->sccp.iucs_remote_addr; + struct hnbgw_cnlink *cnlink = is_ps ? g_hnbgw->sccp.cnlink_iups : g_hnbgw->sccp.cnlink_iucs; + if (!cnlink) + return NULL; + return &cnlink->remote_addr; +} + +static bool cnlink_matches(const struct hnbgw_cnlink *cnlink, const struct hnbgw_sccp_user *hsu, const struct osmo_sccp_addr *remote_addr) +{ + if (cnlink->hnbgw_sccp_user != hsu) + return false; + if (osmo_sccp_addr_cmp(&cnlink->remote_addr, remote_addr, OSMO_SCCP_ADDR_T_SSN | OSMO_SCCP_ADDR_T_PC)) + return false; + return true; +} +struct hnbgw_cnlink *hnbgw_cnlink_find_by_addr(const struct hnbgw_sccp_user *hsu, + const struct osmo_sccp_addr *remote_addr) +{ + /* FUTURE: loop over llist g_hnb_gw->sccp.cnpool */ + if (cnlink_matches(g_hnbgw->sccp.cnlink_iucs, hsu, remote_addr)) + return g_hnbgw->sccp.cnlink_iucs; + if (cnlink_matches(g_hnbgw->sccp.cnlink_iups, hsu, remote_addr)) + return g_hnbgw->sccp.cnlink_iups; + return NULL; +} + +struct hnbgw_cnlink *hnbgw_cnlink_select(bool is_ps) +{ + /* FUTURE: soon we will pick one of many configurable CN peers from a pool. There will be more input arguments + * (MI, or TMSI, or NRI decoded from RANAP) and this function will do round robin for new subscribers. */ + if (is_ps) + return g_hnbgw->sccp.cnlink_iups; + return g_hnbgw->sccp.cnlink_iucs; +} + +char *cnlink_sccp_addr_to_str(struct hnbgw_cnlink *cnlink, const struct osmo_sccp_addr *addr) +{ + struct osmo_sccp_instance *sccp = cnlink_sccp(cnlink); + if (!sccp) + return osmo_sccp_addr_dump(addr); + return osmo_sccp_inst_addr_to_str_c(OTC_SELECT, sccp, addr); } diff --git a/src/osmo-hnbgw/hnbgw_rua.c b/src/osmo-hnbgw/hnbgw_rua.c index 2e03e01..8157cfc 100644 --- a/src/osmo-hnbgw/hnbgw_rua.c +++ b/src/osmo-hnbgw/hnbgw_rua.c @@ -200,7 +200,6 @@ { struct msgb *ranap_msg = NULL; struct hnbgw_context_map *map = NULL; - struct hnbgw_cnlink *cn = g_hnbgw->sccp.cnlink; bool is_ps;
switch (cN_DomainIndicator) { @@ -215,11 +214,6 @@ return -1; }
- if (!cn) { - LOGHNB(hnb, DRUA, LOGL_NOTICE, "CN=NULL, discarding message\n"); - return 0; - } - /* If there is RANAP data, include it in the msgb. In RUA there is always data in practice, but theoretically it * could be an empty Connect or Disconnect. */ if (data && len) { @@ -230,8 +224,13 @@ memcpy(ranap_msg->l2h, data, len); }
- map = context_map_alloc_by_hnb(hnb, context_id, is_ps, cn); - OSMO_ASSERT(map); + map = context_map_find_or_create_by_rua_ctx_id(hnb, context_id, is_ps); + if (!map) { + LOGHNB(hnb, DRUA, LOGL_ERROR, + "Failed to create context map for %s: rx RUA %s with %u bytes RANAP data\n", + is_ps ? "IuPS" : "IuCS", rua_procedure_code_name(rua_procedure), data ? len : 0); + return -1; + }
LOG_MAP(map, DRUA, LOGL_DEBUG, "rx RUA %s with %u bytes RANAP data\n", rua_procedure_code_name(rua_procedure), data ? len : 0); diff --git a/src/osmo-hnbgw/hnbgw_vty.c b/src/osmo-hnbgw/hnbgw_vty.c index 47db695..c1ff268 100644 --- a/src/osmo-hnbgw/hnbgw_vty.c +++ b/src/osmo-hnbgw/hnbgw_vty.c @@ -29,6 +29,7 @@ #include <osmocom/hnbgw/vty.h>
#include <osmocom/hnbgw/hnbgw.h> +#include <osmocom/hnbgw/hnbgw_cn.h> #include <osmocom/hnbgw/context_map.h> #include <osmocom/hnbgw/tdefs.h> #include <osmocom/sigtran/protocol/sua.h> @@ -108,36 +109,51 @@ return vty->node; }
+static void _show_cnlink(struct vty *vty, struct hnbgw_cnlink *cnlink) +{ + struct osmo_ss7_route *rt; + struct osmo_ss7_instance *ss7; + + if (!cnlink) { + vty_out(vty, "NULL%s", VTY_NEWLINE); + return; + } + + if (!cnlink->hnbgw_sccp_user) { + vty_out(vty, "no SCCP state%s", VTY_NEWLINE); + return; + } + + ss7 = cnlink->hnbgw_sccp_user->ss7; + if (!ss7) { + vty_out(vty, "no cs7 instance%s", VTY_NEWLINE); + return; + } + + if (!cnlink->hnbgw_sccp_user->sccp_user) { + vty_out(vty, "no SCCP user%s", VTY_NEWLINE); + return; + } + + vty_out(vty, "%s <->", + osmo_sccp_user_name(cnlink->hnbgw_sccp_user->sccp_user)); + vty_out(vty, " %s%s%s%s", + cnlink->remote_addr_name ? : "", + cnlink->remote_addr_name ? "=" : "", + cnlink_sccp_addr_to_str(cnlink, &cnlink->remote_addr), + VTY_NEWLINE); + + rt = osmo_ss7_route_lookup(ss7, cnlink->remote_addr.pc); + vty_out(vty, " SS7 route: %s%s", osmo_ss7_route_name(rt, true), VTY_NEWLINE); +} + DEFUN(show_cnlink, show_cnlink_cmd, "show cnlink", SHOW_STR "Display information on core network link\n") { - struct osmo_ss7_route *rt; - struct osmo_ss7_instance *ss7 = osmo_sccp_get_ss7(g_hnbgw->sccp.client); -#define GUARD(STR) \ - STR ? STR : "", \ - STR ? ":" : "" - - vty_out(vty, "IuCS: %s <->", - osmo_sccp_user_name(g_hnbgw->sccp.cnlink->sccp_user)); - vty_out(vty, " %s%s%s%s", - GUARD(g_hnbgw->config.iucs_remote_addr_name), - osmo_sccp_inst_addr_name(g_hnbgw->sccp.client, &g_hnbgw->sccp.iucs_remote_addr), - VTY_NEWLINE); - - rt = osmo_ss7_route_lookup(ss7, g_hnbgw->sccp.iucs_remote_addr.pc); - vty_out(vty, " SS7 route: %s%s", osmo_ss7_route_name(rt, true), VTY_NEWLINE); - - vty_out(vty, "IuPS: %s <->", - osmo_sccp_user_name(g_hnbgw->sccp.cnlink->sccp_user)); - vty_out(vty, " %s%s%s%s", - GUARD(g_hnbgw->config.iups_remote_addr_name), - osmo_sccp_inst_addr_name(g_hnbgw->sccp.client, &g_hnbgw->sccp.iups_remote_addr), - VTY_NEWLINE); - - rt = osmo_ss7_route_lookup(ss7, g_hnbgw->sccp.iups_remote_addr.pc); - vty_out(vty, " SS7 route: %s%s", osmo_ss7_route_name(rt, true), VTY_NEWLINE); - -#undef GUARD + vty_out(vty, "IuCS: "); + _show_cnlink(vty, g_hnbgw->sccp.cnlink_iucs); + vty_out(vty, "IuPS: "); + _show_cnlink(vty, g_hnbgw->sccp.cnlink_iups); return CMD_SUCCESS; }
diff --git a/src/osmo-hnbgw/osmo_hnbgw_main.c b/src/osmo-hnbgw/osmo_hnbgw_main.c index 28ff42a..4994b1f 100644 --- a/src/osmo-hnbgw/osmo_hnbgw_main.c +++ b/src/osmo-hnbgw/osmo_hnbgw_main.c @@ -259,11 +259,13 @@
ranap_set_log_area(DRANAP);
- rc = hnbgw_cnlink_init("localhost", M3UA_PORT, "localhost"); - if (rc < 0) { + if (!hnbgw_cnlink_alloc(g_hnbgw->config.iucs_remote_addr_name, DOMAIN_CS) + || !hnbgw_cnlink_alloc(g_hnbgw->config.iups_remote_addr_name, DOMAIN_PS)) { LOGP(DMAIN, LOGL_ERROR, "Failed to initialize SCCP link to CN\n"); exit(1); } + OSMO_ASSERT(g_hnbgw->sccp.cnlink_iucs); + OSMO_ASSERT(g_hnbgw->sccp.cnlink_iups);
LOGP(DHNBAP, LOGL_NOTICE, "Using RNC-Id %u\n", g_hnbgw->config.rnc_id);
diff --git a/tests/config/defaults.vty b/tests/config/defaults.vty index 282c080..35119b1 100644 --- a/tests/config/defaults.vty +++ b/tests/config/defaults.vty @@ -5,19 +5,19 @@ OsmoHNBGW# show cs7 config cs7 instance 0 point-code 0.23.5 - asp asp-clnt-OsmoHNBGW 2905 0 m3ua + asp asp-clnt-msc-0 2905 0 m3ua local-ip localhost remote-ip localhost sctp-role client - as as-clnt-OsmoHNBGW m3ua - asp asp-clnt-OsmoHNBGW + as as-clnt-msc-0 m3ua + asp asp-clnt-msc-0 routing-key 0 0.23.5
OsmoHNBGW# show cnlink IuCS: OsmoHNBGW:RI=SSN_PC,PC=0.23.5,SSN=RANAP <-> RI=SSN_PC,PC=0.23.1,SSN=RANAP - SS7 route: pc=0=0.0.0 mask=0x0=0.0.0 via AS as-clnt-OsmoHNBGW proto=m3ua ASP asp-clnt-OsmoHNBGW + SS7 route: pc=0=0.0.0 mask=0x0=0.0.0 via AS as-clnt-msc-0 proto=m3ua ASP asp-clnt-msc-0 IuPS: OsmoHNBGW:RI=SSN_PC,PC=0.23.5,SSN=RANAP <-> RI=SSN_PC,PC=0.23.4,SSN=RANAP - SS7 route: pc=0=0.0.0 mask=0x0=0.0.0 via AS as-clnt-OsmoHNBGW proto=m3ua ASP asp-clnt-OsmoHNBGW + SS7 route: pc=0=0.0.0 mask=0x0=0.0.0 via AS as-clnt-msc-0 proto=m3ua ASP asp-clnt-msc-0
OsmoHNBGW# show running-config ... diff --git a/tests/config/one_cs7.vty b/tests/config/one_cs7.vty index 7011c83..7196ef8 100644 --- a/tests/config/one_cs7.vty +++ b/tests/config/one_cs7.vty @@ -1,28 +1,25 @@ OsmoHNBGW> enable
-OsmoHNBGW# ### ERROR: 'one_cs7.cfg' sets 'cs7 instance 0' / 'point-code 1.1.1', but osmo-hnbgw uses 0.23.5 OsmoHNBGW# show cs7 config cs7 instance 0 - point-code 0.23.5 - asp asp-clnt-OsmoHNBGW 2905 0 m3ua + point-code 1.1.1 + asp asp-clnt-msc-0 2905 0 m3ua local-ip localhost remote-ip localhost sctp-role client - as as-clnt-OsmoHNBGW m3ua - asp asp-clnt-OsmoHNBGW - routing-key 0 0.23.5 + as as-clnt-msc-0 m3ua + asp asp-clnt-msc-0 + routing-key 0 1.1.1
-OsmoHNBGW# ### ERROR: 'one_cs7.cfg' sets 'cs7 instance 0' / 'point-code 1.1.1', but osmo-hnbgw uses 0.23.5 OsmoHNBGW# show cnlink -IuCS: OsmoHNBGW:RI=SSN_PC,PC=0.23.5,SSN=RANAP <-> RI=SSN_PC,PC=0.23.1,SSN=RANAP - SS7 route: pc=0=0.0.0 mask=0x0=0.0.0 via AS as-clnt-OsmoHNBGW proto=m3ua ASP asp-clnt-OsmoHNBGW -IuPS: OsmoHNBGW:RI=SSN_PC,PC=0.23.5,SSN=RANAP <-> RI=SSN_PC,PC=0.23.4,SSN=RANAP - SS7 route: pc=0=0.0.0 mask=0x0=0.0.0 via AS as-clnt-OsmoHNBGW proto=m3ua ASP asp-clnt-OsmoHNBGW +IuCS: OsmoHNBGW:RI=SSN_PC,PC=1.1.1,SSN=RANAP <-> RI=SSN_PC,PC=0.23.1,SSN=RANAP + SS7 route: pc=0=0.0.0 mask=0x0=0.0.0 via AS as-clnt-msc-0 proto=m3ua ASP asp-clnt-msc-0 +IuPS: OsmoHNBGW:RI=SSN_PC,PC=1.1.1,SSN=RANAP <-> RI=SSN_PC,PC=0.23.4,SSN=RANAP + SS7 route: pc=0=0.0.0 mask=0x0=0.0.0 via AS as-clnt-msc-0 proto=m3ua ASP asp-clnt-msc-0
-OsmoHNBGW# ### ERROR: 'one_cs7.cfg' sets 'cs7 instance 0' / 'point-code 1.1.1', but osmo-hnbgw uses 0.23.5 OsmoHNBGW# show running-config ... cs7 instance 0 - point-code 0.23.5 + point-code 1.1.1 hnbgw ... diff --git a/tests/config/one_cs7_with_addrs.vty b/tests/config/one_cs7_with_addrs.vty index 59b1b76..2975ade 100644 --- a/tests/config/one_cs7_with_addrs.vty +++ b/tests/config/one_cs7_with_addrs.vty @@ -4,12 +4,12 @@ OsmoHNBGW# show cs7 config cs7 instance 0 point-code 1.1.1 - asp asp-clnt-OsmoHNBGW 2905 0 m3ua + asp asp-clnt-msc-0 2905 0 m3ua local-ip localhost remote-ip localhost sctp-role client - as as-clnt-OsmoHNBGW m3ua - asp asp-clnt-OsmoHNBGW + as as-clnt-msc-0 m3ua + asp asp-clnt-msc-0 routing-key 0 1.1.1 sccp-address my-msc routing-indicator PC @@ -20,10 +20,10 @@
OsmoHNBGW# ### IuCS and IuPS were explicitly pointed to specific remote point-codes, using cs7 instance 0 addresses OsmoHNBGW# show cnlink -IuCS: OsmoHNBGW:RI=SSN_PC,PC=1.1.1,SSN=RANAP <-> my-msc:RI=SSN_PC,PC=1.2.3,SSN=RANAP - SS7 route: pc=0=0.0.0 mask=0x0=0.0.0 via AS as-clnt-OsmoHNBGW proto=m3ua ASP asp-clnt-OsmoHNBGW -IuPS: OsmoHNBGW:RI=SSN_PC,PC=1.1.1,SSN=RANAP <-> my-sgsn:RI=SSN_PC,PC=1.4.2,SSN=RANAP - SS7 route: pc=0=0.0.0 mask=0x0=0.0.0 via AS as-clnt-OsmoHNBGW proto=m3ua ASP asp-clnt-OsmoHNBGW +IuCS: OsmoHNBGW:RI=SSN_PC,PC=1.1.1,SSN=RANAP <-> my-msc=RI=SSN_PC,PC=1.2.3,SSN=RANAP + SS7 route: pc=0=0.0.0 mask=0x0=0.0.0 via AS as-clnt-msc-0 proto=m3ua ASP asp-clnt-msc-0 +IuPS: OsmoHNBGW:RI=SSN_PC,PC=1.1.1,SSN=RANAP <-> my-sgsn=RI=SSN_PC,PC=1.4.2,SSN=RANAP + SS7 route: pc=0=0.0.0 mask=0x0=0.0.0 via AS as-clnt-msc-0 proto=m3ua ASP asp-clnt-msc-0
OsmoHNBGW# show running-config ... diff --git a/tests/config/one_cs7_with_iucs_addr.vty b/tests/config/one_cs7_with_iucs_addr.vty index 2e57ea1..7fc4ed1 100644 --- a/tests/config/one_cs7_with_iucs_addr.vty +++ b/tests/config/one_cs7_with_iucs_addr.vty @@ -3,12 +3,12 @@ OsmoHNBGW# show cs7 config cs7 instance 0 point-code 1.1.1 - asp asp-clnt-OsmoHNBGW 2905 0 m3ua + asp asp-clnt-msc-0 2905 0 m3ua local-ip localhost remote-ip localhost sctp-role client - as as-clnt-OsmoHNBGW m3ua - asp asp-clnt-OsmoHNBGW + as as-clnt-msc-0 m3ua + asp asp-clnt-msc-0 routing-key 0 1.1.1 sccp-address my-msc routing-indicator PC @@ -16,10 +16,10 @@
OsmoHNBGW# ### only IuCS was configured to go to remote-PC = 1.2.3, IuPS auto-configured to remote-PC = 0.23.4 OsmoHNBGW# show cnlink -IuCS: OsmoHNBGW:RI=SSN_PC,PC=1.1.1,SSN=RANAP <-> my-msc:RI=SSN_PC,PC=1.2.3,SSN=RANAP - SS7 route: pc=0=0.0.0 mask=0x0=0.0.0 via AS as-clnt-OsmoHNBGW proto=m3ua ASP asp-clnt-OsmoHNBGW +IuCS: OsmoHNBGW:RI=SSN_PC,PC=1.1.1,SSN=RANAP <-> my-msc=RI=SSN_PC,PC=1.2.3,SSN=RANAP + SS7 route: pc=0=0.0.0 mask=0x0=0.0.0 via AS as-clnt-msc-0 proto=m3ua ASP asp-clnt-msc-0 IuPS: OsmoHNBGW:RI=SSN_PC,PC=1.1.1,SSN=RANAP <-> RI=SSN_PC,PC=0.23.4,SSN=RANAP - SS7 route: pc=0=0.0.0 mask=0x0=0.0.0 via AS as-clnt-OsmoHNBGW proto=m3ua ASP asp-clnt-OsmoHNBGW + SS7 route: pc=0=0.0.0 mask=0x0=0.0.0 via AS as-clnt-msc-0 proto=m3ua ASP asp-clnt-msc-0
OsmoHNBGW# show running-config ... diff --git a/tests/config/one_cs7_with_iups_addr.vty b/tests/config/one_cs7_with_iups_addr.vty index 1e4346f..bd5f261 100644 --- a/tests/config/one_cs7_with_iups_addr.vty +++ b/tests/config/one_cs7_with_iups_addr.vty @@ -3,12 +3,12 @@ OsmoHNBGW# show cs7 config cs7 instance 0 point-code 1.1.1 - asp asp-clnt-OsmoHNBGW 2905 0 m3ua + asp asp-clnt-msc-0 2905 0 m3ua local-ip localhost remote-ip localhost sctp-role client - as as-clnt-OsmoHNBGW m3ua - asp asp-clnt-OsmoHNBGW + as as-clnt-msc-0 m3ua + asp asp-clnt-msc-0 routing-key 0 1.1.1 sccp-address my-sgsn routing-indicator PC @@ -17,9 +17,9 @@ OsmoHNBGW# ### only IuPS was configured to go to remote-PC = 1.4.2, IuCS auto-configured to remote-PC = 0.23.1 OsmoHNBGW# show cnlink IuCS: OsmoHNBGW:RI=SSN_PC,PC=1.1.1,SSN=RANAP <-> RI=SSN_PC,PC=0.23.1,SSN=RANAP - SS7 route: pc=0=0.0.0 mask=0x0=0.0.0 via AS as-clnt-OsmoHNBGW proto=m3ua ASP asp-clnt-OsmoHNBGW -IuPS: OsmoHNBGW:RI=SSN_PC,PC=1.1.1,SSN=RANAP <-> my-sgsn:RI=SSN_PC,PC=1.4.2,SSN=RANAP - SS7 route: pc=0=0.0.0 mask=0x0=0.0.0 via AS as-clnt-OsmoHNBGW proto=m3ua ASP asp-clnt-OsmoHNBGW + SS7 route: pc=0=0.0.0 mask=0x0=0.0.0 via AS as-clnt-msc-0 proto=m3ua ASP asp-clnt-msc-0 +IuPS: OsmoHNBGW:RI=SSN_PC,PC=1.1.1,SSN=RANAP <-> my-sgsn=RI=SSN_PC,PC=1.4.2,SSN=RANAP + SS7 route: pc=0=0.0.0 mask=0x0=0.0.0 via AS as-clnt-msc-0 proto=m3ua ASP asp-clnt-msc-0
OsmoHNBGW# show running-config ... diff --git a/tests/config/two_cs7.cfg b/tests/config/two_cs7.cfg new file mode 100644 index 0000000..9f5eba0 --- /dev/null +++ b/tests/config/two_cs7.cfg @@ -0,0 +1,7 @@ +# there are two cs7 instances, but auto-configuration will only use instance 0. + +cs7 instance 0 + point-code 1.1.1 + +cs7 instance 1 + point-code 2.2.2 diff --git a/tests/config/two_cs7.vty b/tests/config/two_cs7.vty new file mode 100644 index 0000000..3d337fa --- /dev/null +++ b/tests/config/two_cs7.vty @@ -0,0 +1,31 @@ +OsmoHNBGW> enable + +OsmoHNBGW# ### there are two cs7 instances, but auto-configuration has only set up ASP and AS in instance 0. +OsmoHNBGW# show cs7 config +cs7 instance 0 + point-code 1.1.1 + asp asp-clnt-msc-0 2905 0 m3ua + local-ip localhost + remote-ip localhost + sctp-role client + as as-clnt-msc-0 m3ua + asp asp-clnt-msc-0 + routing-key 0 1.1.1 +cs7 instance 1 + point-code 2.2.2 + +OsmoHNBGW# ### there are two cs7 instances, but auto-configuration will only use SCCP of instance 0 with local-PC = 1.1.1 +OsmoHNBGW# show cnlink +IuCS: OsmoHNBGW:RI=SSN_PC,PC=1.1.1,SSN=RANAP <-> RI=SSN_PC,PC=0.23.1,SSN=RANAP + SS7 route: pc=0=0.0.0 mask=0x0=0.0.0 via AS as-clnt-msc-0 proto=m3ua ASP asp-clnt-msc-0 +IuPS: OsmoHNBGW:RI=SSN_PC,PC=1.1.1,SSN=RANAP <-> RI=SSN_PC,PC=0.23.4,SSN=RANAP + SS7 route: pc=0=0.0.0 mask=0x0=0.0.0 via AS as-clnt-msc-0 proto=m3ua ASP asp-clnt-msc-0 + +OsmoHNBGW# show running-config +... +cs7 instance 0 + point-code 1.1.1 +cs7 instance 1 + point-code 2.2.2 +hnbgw +... diff --git a/tests/config/two_cs7_with_addrs.cfg b/tests/config/two_cs7_with_addrs.cfg new file mode 100644 index 0000000..57f13e3 --- /dev/null +++ b/tests/config/two_cs7_with_addrs.cfg @@ -0,0 +1,17 @@ +# two cs7 instances, both will be auto-configured for ASP and AS because address book entries point at both. + +cs7 instance 0 + point-code 1.1.1 + sccp-address my-msc + point-code 1.2.3 + +cs7 instance 1 + point-code 2.2.2 + sccp-address my-sgsn + point-code 2.4.2 + +hnbgw + iucs + remote-addr my-msc + iups + remote-addr my-sgsn diff --git a/tests/config/two_cs7_with_addrs.vty b/tests/config/two_cs7_with_addrs.vty new file mode 100644 index 0000000..59240d1 --- /dev/null +++ b/tests/config/two_cs7_with_addrs.vty @@ -0,0 +1,57 @@ +OsmoHNBGW> enable + +OsmoHNBGW# ### two cs7 instances, both have been auto-configured for ASP and AS because address book entries point at both. +OsmoHNBGW# show cs7 config +cs7 instance 0 + point-code 1.1.1 + asp asp-clnt-msc-0 2905 0 m3ua + local-ip localhost + remote-ip localhost + sctp-role client + as as-clnt-msc-0 m3ua + asp asp-clnt-msc-0 + routing-key 0 1.1.1 + sccp-address my-msc + routing-indicator PC + point-code 1.2.3 +cs7 instance 1 + point-code 2.2.2 + asp asp-clnt-sgsn-0 2905 0 m3ua + local-ip localhost + remote-ip localhost + sctp-role client + as as-clnt-sgsn-0 m3ua + asp asp-clnt-sgsn-0 + routing-key 0 2.2.2 + sccp-address my-sgsn + routing-indicator PC + point-code 2.4.2 + +OsmoHNBGW# ### IuCS on instance 0 with local-PC = 1.1.1, IuPS on instance 1 with local-PC = 2.2.2 +OsmoHNBGW# show cnlink +IuCS: OsmoHNBGW:RI=SSN_PC,PC=1.1.1,SSN=RANAP <-> my-msc=RI=SSN_PC,PC=1.2.3,SSN=RANAP + SS7 route: pc=0=0.0.0 mask=0x0=0.0.0 via AS as-clnt-msc-0 proto=m3ua ASP asp-clnt-msc-0 +IuPS: OsmoHNBGW:RI=SSN_PC,PC=2.2.2,SSN=RANAP <-> my-sgsn=RI=SSN_PC,PC=2.4.2,SSN=RANAP + SS7 route: pc=0=0.0.0 mask=0x0=0.0.0 via AS as-clnt-sgsn-0 proto=m3ua ASP asp-clnt-sgsn-0 + +OsmoHNBGW# show running-config +... +cs7 instance 0 + point-code 1.1.1 + sccp-address my-msc + routing-indicator PC + point-code 1.2.3 +cs7 instance 1 + point-code 2.2.2 + sccp-address my-sgsn + routing-indicator PC + point-code 2.4.2 +hnbgw + rnc-id 23 + log-prefix hnb-id + iuh + iucs + remote-addr my-msc + iups + remote-addr my-sgsn +...