cnpool: add multiple 'msc' and 'sgsn' cfg (use only the first)
Allow configuring multiple MSCs and SGSNs. Show this in new transcript test cnpool.vty and in sccp.dot chart. Still use only the first CN link; actual CN link selection from the pool follows in I66fba27cfbe6e2b27ee3443718846ecfbbd8a974. Config examples and VTY tests cfg files will be adjusted to the new cfg syntax in patch If999b71a8a8237699f6ccfcaa31d1885e66c0518. Only the VTY write() changes are visible here, to pass all transcript tests. Related: SYS#6412 Change-Id: I5479eded786ec26062d49403a8be12967f113cdb
This commit is contained in:
parent
bd5901d3f9
commit
9901316371
|
@ -9,13 +9,15 @@ labelloc=t; label="SCCP/SS7 use in OsmoHNBGW"
|
|||
ss0 -> ss0ab
|
||||
|
||||
msc0a [label="2.2.2"]
|
||||
ss0ab -> msc0a
|
||||
sgsn0a [label="3.3.3"]
|
||||
msc1a [label="5.5.5"]
|
||||
ss0ab -> msc0a,sgsn0a,msc1a
|
||||
}
|
||||
|
||||
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"];
|
||||
sccp0 [label="hnbgw_sccp_user for '0'\n .osmo_sccp_instance\n .osmo_ss7_user SSN: RANAP"];
|
||||
ss0 -> sccp0 [dir=back]
|
||||
|
||||
msc0 [label="hnbgw_cnlink for IuCS\n .remote_addr -> 2.2.2"]
|
||||
msc0 [label="hnbgw_cnlink 'msc0'\n .domain = IuCS\n .sccp_addr -> 2.2.2"]
|
||||
sccp0 -> msc0 [dir=back]
|
||||
msc0a -> msc0 [dir=back]
|
||||
|
||||
|
@ -23,26 +25,39 @@ labelloc=t; label="SCCP/SS7 use in OsmoHNBGW"
|
|||
cs1 [label="UE CS conn\n hnbgw_context_map"]
|
||||
msc0 -> cs0,cs1
|
||||
|
||||
sgsn0 [label="hnbgw_cnlink 'sgsn0'\n .domain = IuPS\n .sccp_addr -> 3.3.3"]
|
||||
sccp0 -> sgsn0 [dir=back]
|
||||
sgsn0a -> sgsn0 [dir=back]
|
||||
|
||||
ps0 [label="UE PS conn\n hnbgw_context_map"]
|
||||
sgsn0 -> ps0
|
||||
|
||||
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
|
||||
sgsn1a [label="6.6.6"]
|
||||
ss1ab -> sgsn1a
|
||||
}
|
||||
|
||||
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"];
|
||||
sccp1 [label="hnbgw_sccp_user for '1'\n .osmo_sccp_instance\n .osmo_ss7_user SSN: RANAP"];
|
||||
ss1 -> sccp1 [dir=back]
|
||||
|
||||
sgsn0 [label="hnbgw_cnlink for IuPS\n .remote_addr -> 3.3.3"]
|
||||
sccp1 -> sgsn0 [dir=back]
|
||||
sgsn0a -> sgsn0 [dir=back]
|
||||
msc1 [label="hnbgw_cnlink 'msc1'\n .domain = IuCS\n .sccp_addr -> 5.5.5"]
|
||||
sccp0 -> msc1 [dir=back]
|
||||
msc1a -> msc1 [dir=back]
|
||||
|
||||
ps0 [label="UE PS conn\n hnbgw_context_map"]
|
||||
ps1 [label="UE PS conn\n hnbgw_context_map"]
|
||||
sgsn0 -> ps0,ps1
|
||||
cs2 [label="UE CS conn\n hnbgw_context_map"]
|
||||
msc1 -> cs2
|
||||
|
||||
sgsn1 [label="hnbgw_cnlink 'sgsn1'\n .domain = IuPS\n .sccp_addr -> 6.6.6"]
|
||||
sccp1 -> sgsn1 [dir=back]
|
||||
sgsn1a -> sgsn1 [dir=back]
|
||||
|
||||
ps2 [label="UE PS conn\n hnbgw_context_map"]
|
||||
sgsn1 -> ps2
|
||||
|
||||
subgraph cluster_sccp_inst {
|
||||
label="global sccp.users (llist)"
|
||||
|
@ -50,9 +65,14 @@ labelloc=t; label="SCCP/SS7 use in OsmoHNBGW"
|
|||
sccp1
|
||||
}
|
||||
|
||||
subgraph cluster_hnbgw {
|
||||
label="global hnbgw"
|
||||
subgraph cluster_cnpool_iucs {
|
||||
label="global cnpool_iucs"
|
||||
msc0
|
||||
msc1
|
||||
}
|
||||
subgraph cluster_cnpool_iups {
|
||||
label="global cnpool_iups"
|
||||
sgsn0
|
||||
sgsn1
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,6 +71,8 @@ struct umts_cell_id {
|
|||
uint32_t cid; /*!< Cell ID */
|
||||
};
|
||||
|
||||
struct hnbgw_context_map;
|
||||
|
||||
/* 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 {
|
||||
|
@ -97,19 +99,62 @@ struct hnbgw_sccp_user {
|
|||
#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. */
|
||||
/* User provided configuration for struct hnbgw_cnpool. */
|
||||
struct hnbgw_cnpool_cfg {
|
||||
/* FUTURE: This will be added here shortly:
|
||||
* - global NRI config: bitlen and NULL-NRI.
|
||||
*/
|
||||
};
|
||||
|
||||
/* User provided configuration for struct hnbgw_cnlink. */
|
||||
struct hnbgw_cnlink_cfg {
|
||||
/* cs7 address book entry to indicate both the remote point-code of the peer, as well as which cs7 instance to
|
||||
* use. */
|
||||
char *remote_addr_name;
|
||||
|
||||
/* FUTURE: This will be added here shortly:
|
||||
* - per peer NRI config: NRI ranges assigned to this peer.
|
||||
*/
|
||||
};
|
||||
|
||||
/* Collection of CN peers to distribute UE connections across. MSCs for DOMAIN_CS, SGSNs for DOMAIN_PS. */
|
||||
struct hnbgw_cnpool {
|
||||
RANAP_CN_DomainIndicator_t domain;
|
||||
|
||||
/* CN pool string used in VTY config and logging, "iucs" or "iups". */
|
||||
const char *pool_name;
|
||||
/* CN peer string used in VTY config and logging, "msc" or "sgsn". */
|
||||
const char *peer_name;
|
||||
/* What we use as the remote MSC/SGSN point-code if the user does not configure any address. */
|
||||
uint32_t default_remote_pc;
|
||||
|
||||
struct hnbgw_cnpool_cfg vty;
|
||||
struct hnbgw_cnpool_cfg use;
|
||||
|
||||
/* List of struct hnbgw_cnlink */
|
||||
struct llist_head cnlinks;
|
||||
|
||||
/* FUTURE: This will be added here shortly:
|
||||
* - round robin state for new conns
|
||||
*/
|
||||
};
|
||||
|
||||
/* A CN peer, like 'msc 0' or 'sgsn 23' */
|
||||
struct hnbgw_cnlink {
|
||||
struct llist_head entry;
|
||||
|
||||
/* backpointer to CS or PS CN pool. */
|
||||
struct hnbgw_cnpool *pool;
|
||||
|
||||
int nr;
|
||||
|
||||
struct hnbgw_cnlink_cfg vty;
|
||||
struct hnbgw_cnlink_cfg use;
|
||||
|
||||
/* 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. */
|
||||
/* Copy of the address book entry use.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
|
||||
|
@ -123,14 +168,16 @@ struct hnbgw_cnlink {
|
|||
#define LOG_CNLINK(CNLINK, SUBSYS, LEVEL, FMT, ARGS...) \
|
||||
LOGP(SUBSYS, LEVEL, "(%s) " FMT, (CNLINK) ? (CNLINK)->name : "null", ##ARGS)
|
||||
|
||||
struct hnbgw_cnlink *cnlink_get_nr(struct hnbgw_cnpool *cnpool, int nr, bool create_if_missing);
|
||||
|
||||
static inline bool cnlink_is_cs(const struct hnbgw_cnlink *cnlink)
|
||||
{
|
||||
return cnlink && cnlink->domain == DOMAIN_CS;
|
||||
return cnlink && cnlink->pool->domain == DOMAIN_CS;
|
||||
}
|
||||
|
||||
static inline bool cnlink_is_ps(const struct hnbgw_cnlink *cnlink)
|
||||
{
|
||||
return cnlink && cnlink->domain == DOMAIN_PS;
|
||||
return cnlink && cnlink->pool->domain == DOMAIN_PS;
|
||||
}
|
||||
|
||||
static inline struct osmo_sccp_instance *cnlink_sccp(const struct hnbgw_cnlink *cnlink)
|
||||
|
@ -186,8 +233,6 @@ struct hnbgw {
|
|||
/*! The UDP port where we receive multiplexed CS user
|
||||
* plane traffic from HNBs */
|
||||
uint16_t iuh_cs_mux_port;
|
||||
const char *iucs_remote_addr_name;
|
||||
const char *iups_remote_addr_name;
|
||||
uint16_t rnc_id;
|
||||
bool hnbap_allow_tmsi;
|
||||
/*! print hnb-id (true) or MCC-MNC-LAC-RAC-SAC (false) in logs */
|
||||
|
@ -213,9 +258,11 @@ struct hnbgw {
|
|||
struct {
|
||||
/* 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;
|
||||
|
||||
/* Pool of core network peers: MSCs for IuCS */
|
||||
struct hnbgw_cnpool cnpool_iucs;
|
||||
/* Pool of core network peers: SGSNs for IuPS */
|
||||
struct hnbgw_cnpool cnpool_iups;
|
||||
} sccp;
|
||||
/* MGW pool, also includes the single MGCP client as fallback if no
|
||||
* pool is configured. */
|
||||
|
|
|
@ -2,12 +2,14 @@
|
|||
|
||||
#include <osmocom/hnbgw/hnbgw.h>
|
||||
|
||||
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);
|
||||
struct hnbgw_cnlink *hnbgw_cnlink_select(struct hnbgw_context_map *map);
|
||||
|
||||
void hnbgw_cnpool_start(struct hnbgw_cnpool *cnpool);
|
||||
void hnbgw_cnpool_apply_cfg(struct hnbgw_cnpool *cnpool);
|
||||
void hnbgw_cnpool_cnlinks_start_or_restart(struct hnbgw_cnpool *cnpool);
|
||||
int hnbgw_cnlink_start_or_restart(struct hnbgw_cnlink *cnlink);
|
||||
|
||||
char *cnlink_sccp_addr_to_str(struct hnbgw_cnlink *cnlink, const struct osmo_sccp_addr *addr);
|
||||
|
||||
|
|
|
@ -10,5 +10,7 @@ enum osmo_iuh_vty_node {
|
|||
MGCP_NODE,
|
||||
MGW_NODE,
|
||||
PFCP_NODE,
|
||||
MSC_NODE,
|
||||
SGSN_NODE,
|
||||
};
|
||||
|
||||
|
|
|
@ -137,7 +137,7 @@ static int tx_sccp_cr(struct osmo_fsm_inst *fi, struct msgb *ranap_msg)
|
|||
|
||||
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.called_addr = map->cnlink->remote_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;
|
||||
|
|
|
@ -60,6 +60,32 @@ void g_hnbgw_alloc(void *ctx)
|
|||
#if ENABLE_PFCP
|
||||
g_hnbgw->config.pfcp.remote_port = OSMO_PFCP_PORT;
|
||||
#endif
|
||||
|
||||
g_hnbgw->sccp.cnpool_iucs = (struct hnbgw_cnpool){
|
||||
.domain = DOMAIN_CS,
|
||||
.pool_name = "iucs",
|
||||
.peer_name = "msc",
|
||||
.default_remote_pc = DEFAULT_PC_MSC,
|
||||
.vty = {
|
||||
/* FUTURE: This will be added here shortly:
|
||||
* - defaults for global NRI config: bitlen and NULL-NRI.
|
||||
*/
|
||||
},
|
||||
};
|
||||
INIT_LLIST_HEAD(&g_hnbgw->sccp.cnpool_iucs.cnlinks);
|
||||
|
||||
g_hnbgw->sccp.cnpool_iups = (struct hnbgw_cnpool){
|
||||
.domain = DOMAIN_PS,
|
||||
.pool_name = "iups",
|
||||
.peer_name = "sgsn",
|
||||
.default_remote_pc = DEFAULT_PC_SGSN,
|
||||
.vty = {
|
||||
/* FUTURE: This will be added here shortly:
|
||||
* - defaults for global NRI config: bitlen and NULL-NRI.
|
||||
*/
|
||||
},
|
||||
};
|
||||
INIT_LLIST_HEAD(&g_hnbgw->sccp.cnpool_iups.cnlinks);
|
||||
}
|
||||
|
||||
static struct hnb_context *hnb_context_by_id(uint32_t cid)
|
||||
|
|
|
@ -60,7 +60,7 @@ static int transmit_rst(struct hnbgw_cnlink *cnlink)
|
|||
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);
|
||||
msg = ranap_new_msg_reset(cnlink->pool->domain, &cause);
|
||||
|
||||
return osmo_sccp_tx_unitdata_msg(cnlink->hnbgw_sccp_user->sccp_user,
|
||||
&cnlink->local_addr,
|
||||
|
@ -84,7 +84,7 @@ static int transmit_reset_ack(struct hnbgw_cnlink *cnlink)
|
|||
cnlink_sccp_addr_to_str(cnlink, &cnlink->hnbgw_sccp_user->local_addr),
|
||||
cnlink_sccp_addr_to_str(cnlink, &cnlink->remote_addr));
|
||||
|
||||
msg = ranap_new_msg_reset_ack(cnlink->domain, NULL);
|
||||
msg = ranap_new_msg_reset_ack(cnlink->pool->domain, NULL);
|
||||
|
||||
return osmo_sccp_tx_unitdata_msg(cnlink->hnbgw_sccp_user->sccp_user,
|
||||
&cnlink->hnbgw_sccp_user->local_addr,
|
||||
|
@ -422,35 +422,83 @@ static int resolve_addr_name(struct osmo_sccp_addr *dest, struct osmo_ss7_instan
|
|||
{
|
||||
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,
|
||||
osmo_sccp_addr_name(*ss7, dest));
|
||||
if (label)
|
||||
LOGP(DMAIN, LOGL_INFO, "%s remote addr not configured, using default: %s\n", label,
|
||||
osmo_sccp_addr_name(*ss7, dest));
|
||||
return 0;
|
||||
}
|
||||
|
||||
*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);
|
||||
if (label)
|
||||
LOGP(DMAIN, LOGL_ERROR, "%s remote addr: no such SCCP address book entry: '%s'\n",
|
||||
label, addr_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
osmo_sccp_addr_set_ssn(dest, OSMO_SCCP_SSN_RANAP);
|
||||
|
||||
if (!addr_has_pc_and_ssn(dest)) {
|
||||
LOGP(DMAIN, LOGL_ERROR, "Invalid/incomplete %s remote-addr: %s\n",
|
||||
label, osmo_sccp_addr_name(*ss7, dest));
|
||||
if (label)
|
||||
LOGP(DMAIN, LOGL_ERROR, "Invalid/incomplete %s remote-addr: %s\n",
|
||||
label, osmo_sccp_addr_name(*ss7, dest));
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOGP(DRANAP, LOGL_NOTICE, "Remote %s SCCP addr: %s\n",
|
||||
label, osmo_sccp_addr_name(*ss7, dest));
|
||||
if (label)
|
||||
LOGP(DRANAP, LOGL_NOTICE, "Remote %s SCCP addr: %s\n",
|
||||
label, osmo_sccp_addr_name(*ss7, dest));
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hnbgw_cnpool_apply_cfg(struct hnbgw_cnpool *cnpool)
|
||||
{
|
||||
cnpool->use = cnpool->vty;
|
||||
}
|
||||
|
||||
static void hnbgw_cnlink_cfg_copy(struct hnbgw_cnlink *cnlink)
|
||||
{
|
||||
osmo_talloc_replace_string(cnlink, &cnlink->use.remote_addr_name, cnlink->vty.remote_addr_name);
|
||||
}
|
||||
|
||||
static bool hnbgw_cnlink_sccp_cfg_changed(struct hnbgw_cnlink *cnlink)
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
if (cnlink->vty.remote_addr_name && cnlink->use.remote_addr_name) {
|
||||
struct osmo_ss7_instance *ss7;
|
||||
struct osmo_sccp_addr remote_addr = {};
|
||||
|
||||
/* Instead of comparing whether the address book entry names are different, actually resolve the
|
||||
* resulting SCCP address, and only restart the cnlink if the resulting address changed. */
|
||||
resolve_addr_name(&remote_addr, &ss7, cnlink->vty.remote_addr_name, NULL, DEFAULT_PC_HNBGW);
|
||||
if (osmo_sccp_addr_cmp(&remote_addr, &cnlink->remote_addr, OSMO_SCCP_ADDR_T_PC | OSMO_SCCP_ADDR_T_SSN))
|
||||
changed = true;
|
||||
} else if (cnlink->vty.remote_addr_name != cnlink->use.remote_addr_name) {
|
||||
/* One of them is NULL, the other is not. */
|
||||
changed = true;
|
||||
}
|
||||
|
||||
/* if more cnlink configuration is added in the future, it needs to be compared here. */
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
static void hnbgw_cnlink_drop_sccp(struct hnbgw_cnlink *cnlink)
|
||||
{
|
||||
struct hnbgw_context_map *map, *map2;
|
||||
|
||||
llist_for_each_entry_safe(map, map2, &cnlink->map_list, hnbgw_cnlink_entry) {
|
||||
map_sccp_dispatch(map, MAP_SCCP_EV_USER_ABORT, NULL);
|
||||
}
|
||||
|
||||
cnlink->hnbgw_sccp_user = NULL;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
int hnbgw_cnlink_start_or_restart(struct hnbgw_cnlink *cnlink)
|
||||
{
|
||||
struct osmo_ss7_instance *ss7 = NULL;
|
||||
struct osmo_sccp_instance *sccp;
|
||||
|
@ -460,39 +508,36 @@ int cnlink_ensure_sccp(struct hnbgw_cnlink *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;
|
||||
if (hnbgw_cnlink_sccp_cfg_changed(cnlink)) {
|
||||
LOG_CNLINK(cnlink, DCN, LOGL_NOTICE, "config changed, restarting SCCP\n");
|
||||
hnbgw_cnlink_drop_sccp(cnlink);
|
||||
} else {
|
||||
LOG_CNLINK(cnlink, DCN, LOGL_DEBUG, "SCCP instance already set up, using %s\n",
|
||||
cnlink->hnbgw_sccp_user->name);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
LOG_CNLINK(cnlink, DCN, LOGL_DEBUG, "no SCCP instance selected yet\n");
|
||||
}
|
||||
LOG_CNLINK(cnlink, DCN, LOGL_DEBUG, "no SCCP instance selected yet\n");
|
||||
|
||||
/* Copy the current configuration: cnlink->use = cnlink->vty */
|
||||
hnbgw_cnlink_cfg_copy(cnlink);
|
||||
|
||||
/* 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,
|
||||
if (cnlink->use.remote_addr_name) {
|
||||
if (resolve_addr_name(&cnlink->remote_addr, &ss7, cnlink->use.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);
|
||||
cnlink->use.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);
|
||||
cnlink->use.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);
|
||||
osmo_sccp_make_addr_pc_ssn(&cnlink->remote_addr, cnlink->pool->default_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.
|
||||
|
@ -563,47 +608,54 @@ int cnlink_ensure_sccp(struct hnbgw_cnlink *cnlink)
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct hnbgw_cnlink *hnbgw_cnlink_alloc(const char *remote_addr_name, RANAP_CN_DomainIndicator_t domain)
|
||||
void hnbgw_cnpool_cnlinks_start_or_restart(struct hnbgw_cnpool *cnpool)
|
||||
{
|
||||
struct hnbgw_cnlink *cnlink;
|
||||
hnbgw_cnpool_apply_cfg(cnpool);
|
||||
llist_for_each_entry(cnlink, &cnpool->cnlinks, entry) {
|
||||
hnbgw_cnlink_start_or_restart(cnlink);
|
||||
}
|
||||
}
|
||||
|
||||
void hnbgw_cnpool_start(struct hnbgw_cnpool *cnpool)
|
||||
{
|
||||
/* Legacy compat: when there is no 'msc N' at all in the config file, set up 'msc 0' with default values (or
|
||||
* 'sgsn' depending on cnpool). */
|
||||
if (llist_empty(&cnpool->cnlinks))
|
||||
cnlink_get_nr(cnpool, 0, true);
|
||||
hnbgw_cnpool_cnlinks_start_or_restart(cnpool);
|
||||
}
|
||||
|
||||
static struct hnbgw_cnlink *cnlink_alloc(struct hnbgw_cnpool *cnpool, int nr)
|
||||
{
|
||||
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),
|
||||
.name = talloc_asprintf(cnlink, "%s-%d", cnpool->peer_name, nr),
|
||||
.pool = cnpool,
|
||||
.nr = nr,
|
||||
.vty = {
|
||||
/* VTY config defaults for the new cnlink */
|
||||
},
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
llist_add_tail(&cnlink->entry, &cnpool->cnlinks);
|
||||
return cnlink;
|
||||
}
|
||||
|
||||
const struct osmo_sccp_addr *hnbgw_cn_get_remote_addr(bool is_ps)
|
||||
struct hnbgw_cnlink *cnlink_get_nr(struct hnbgw_cnpool *cnpool, int nr, bool create_if_missing)
|
||||
{
|
||||
struct hnbgw_cnlink *cnlink = is_ps ? g_hnbgw->sccp.cnlink_iups : g_hnbgw->sccp.cnlink_iucs;
|
||||
if (!cnlink)
|
||||
struct hnbgw_cnlink *cnlink;
|
||||
llist_for_each_entry(cnlink, &cnpool->cnlinks, entry) {
|
||||
if (cnlink->nr == nr)
|
||||
return cnlink;
|
||||
}
|
||||
|
||||
if (!create_if_missing)
|
||||
return NULL;
|
||||
return &cnlink->remote_addr;
|
||||
|
||||
return cnlink_alloc(cnpool, nr);
|
||||
}
|
||||
|
||||
static bool cnlink_matches(const struct hnbgw_cnlink *cnlink, const struct hnbgw_sccp_user *hsu, const struct osmo_sccp_addr *remote_addr)
|
||||
|
@ -614,24 +666,37 @@ static bool cnlink_matches(const struct hnbgw_cnlink *cnlink, const struct hnbgw
|
|||
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;
|
||||
struct hnbgw_cnlink *cnlink;
|
||||
llist_for_each_entry(cnlink, &g_hnbgw->sccp.cnpool_iucs.cnlinks, entry) {
|
||||
if (cnlink_matches(cnlink, hsu, remote_addr))
|
||||
return cnlink;
|
||||
}
|
||||
llist_for_each_entry(cnlink, &g_hnbgw->sccp.cnpool_iups.cnlinks, entry) {
|
||||
if (cnlink_matches(cnlink, hsu, remote_addr))
|
||||
return cnlink;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct hnbgw_cnlink *hnbgw_cnlink_select(bool is_ps)
|
||||
struct hnbgw_cnlink *hnbgw_cnlink_select(struct hnbgw_context_map *map)
|
||||
{
|
||||
struct hnbgw_cnpool *cnpool = map->is_ps ? &g_hnbgw->sccp.cnpool_iups : &g_hnbgw->sccp.cnpool_iucs;
|
||||
struct hnbgw_cnlink *cnlink;
|
||||
/* 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;
|
||||
llist_for_each_entry(cnlink, &cnpool->cnlinks, entry) {
|
||||
if (!cnlink->hnbgw_sccp_user || !cnlink->hnbgw_sccp_user->sccp_user)
|
||||
continue;
|
||||
LOG_MAP(map, DCN, LOGL_INFO, "Selected %s / %s\n",
|
||||
cnlink->name,
|
||||
cnlink->hnbgw_sccp_user->name);
|
||||
return cnlink;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *cnlink_sccp_addr_to_str(struct hnbgw_cnlink *cnlink, const struct osmo_sccp_addr *addr)
|
||||
|
|
|
@ -74,6 +74,7 @@ DEFUN(cfg_hnbgw_iucs, cfg_hnbgw_iucs_cmd,
|
|||
"iucs", "Configure IuCS options")
|
||||
{
|
||||
vty->node = IUCS_NODE;
|
||||
vty->index = &g_hnbgw->sccp.cnpool_iucs;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -87,6 +88,7 @@ DEFUN(cfg_hnbgw_iups, cfg_hnbgw_iups_cmd,
|
|||
"iups", "Configure IuPS options")
|
||||
{
|
||||
vty->node = IUPS_NODE;
|
||||
vty->index = &g_hnbgw->sccp.cnpool_iups;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -138,8 +140,8 @@ static void _show_cnlink(struct vty *vty, struct hnbgw_cnlink *cnlink)
|
|||
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->use.remote_addr_name ? : "",
|
||||
cnlink->use.remote_addr_name ? "=" : "",
|
||||
cnlink_sccp_addr_to_str(cnlink, &cnlink->remote_addr),
|
||||
VTY_NEWLINE);
|
||||
|
||||
|
@ -150,10 +152,13 @@ static void _show_cnlink(struct vty *vty, struct hnbgw_cnlink *cnlink)
|
|||
DEFUN(show_cnlink, show_cnlink_cmd, "show cnlink",
|
||||
SHOW_STR "Display information on core network link\n")
|
||||
{
|
||||
struct hnbgw_cnlink *cnlink;
|
||||
vty_out(vty, "IuCS: ");
|
||||
_show_cnlink(vty, g_hnbgw->sccp.cnlink_iucs);
|
||||
llist_for_each_entry(cnlink, &g_hnbgw->sccp.cnpool_iucs.cnlinks, entry)
|
||||
_show_cnlink(vty, cnlink);
|
||||
vty_out(vty, "IuPS: ");
|
||||
_show_cnlink(vty, g_hnbgw->sccp.cnlink_iups);
|
||||
llist_for_each_entry(cnlink, &g_hnbgw->sccp.cnpool_iups.cnlinks, entry)
|
||||
_show_cnlink(vty, cnlink);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -341,23 +346,130 @@ DEFUN_DEPRECATED(cfg_hnbgw_max_sccp_cr_payload_len, cfg_hnbgw_max_sccp_cr_payloa
|
|||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
DEFUN(cfg_hnbgw_iucs_remote_addr,
|
||||
cfg_hnbgw_iucs_remote_addr_cmd,
|
||||
"remote-addr NAME",
|
||||
"SCCP address to send IuCS to (MSC)\n"
|
||||
"SCCP address book entry name (see 'cs7-instance')\n")
|
||||
/* Legacy from when there was only one IuCS and one IuPS peer. Instead, there are now 'msc 123' / 'sgsn 123' sub nodes.
|
||||
* To yield legacy behavior, set the first cnlink config in this pool ('msc 0' / 'sgsn 0'). */
|
||||
DEFUN_DEPRECATED(cfg_hnbgw_cnpool_remote_addr,
|
||||
cfg_hnbgw_cnpool_remote_addr_cmd,
|
||||
"remote-addr NAME",
|
||||
"Deprecated command: same as '{msc,sgsn} 0' / 'remote-addr NAME'\n-\n")
|
||||
{
|
||||
g_hnbgw->config.iucs_remote_addr_name = talloc_strdup(g_hnbgw, argv[0]);
|
||||
const char *logmsg;
|
||||
struct hnbgw_cnpool *cnpool = vty->index;
|
||||
struct hnbgw_cnlink *cnlink = cnlink_get_nr(cnpool, 0, true);
|
||||
OSMO_ASSERT(cnlink);
|
||||
cnlink->vty.remote_addr_name = talloc_strdup(cnlink, argv[0]);
|
||||
|
||||
logmsg = talloc_asprintf(OTC_SELECT,
|
||||
"Deprecated: instead of hnbgw/%s/remote-addr,"
|
||||
" use '%s 0'/remote-addr",
|
||||
cnpool->pool_name,
|
||||
cnpool->peer_name);
|
||||
vty_out(vty, "%% %s%s", logmsg, VTY_NEWLINE);
|
||||
LOGP(DLGLOBAL, LOGL_ERROR, "config: %s\n", logmsg);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_hnbgw_iups_remote_addr,
|
||||
cfg_hnbgw_iups_remote_addr_cmd,
|
||||
"remote-addr NAME",
|
||||
"SCCP address to send IuPS to (SGSN)\n"
|
||||
"SCCP address book entry name (see 'cs7-instance')\n")
|
||||
#define CNLINK_NR_RANGE "<0-1000>"
|
||||
|
||||
static struct cmd_node msc_node = {
|
||||
MSC_NODE,
|
||||
"%s(config-msc)# ",
|
||||
1,
|
||||
};
|
||||
|
||||
static struct cmd_node sgsn_node = {
|
||||
SGSN_NODE,
|
||||
"%s(config-sgsn)# ",
|
||||
1,
|
||||
};
|
||||
|
||||
/* Commands that are common for 'msc 0' and 'sgsn 0' */
|
||||
|
||||
static int cnlink_nr(struct vty *vty, struct hnbgw_cnpool *cnpool, int argc, const char **argv)
|
||||
{
|
||||
g_hnbgw->config.iups_remote_addr_name = talloc_strdup(g_hnbgw, argv[0]);
|
||||
int nr = atoi(argv[0]);
|
||||
struct hnbgw_cnlink *cnlink = cnlink_get_nr(cnpool, nr, true);
|
||||
OSMO_ASSERT(cnlink);
|
||||
switch (cnpool->domain) {
|
||||
case DOMAIN_CS:
|
||||
vty->node = MSC_NODE;
|
||||
break;
|
||||
case DOMAIN_PS:
|
||||
vty->node = SGSN_NODE;
|
||||
break;
|
||||
default:
|
||||
OSMO_ASSERT(false);
|
||||
}
|
||||
vty->index = cnlink;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
/* 'msc 0' */
|
||||
DEFUN(cfg_msc_nr, cfg_msc_nr_cmd,
|
||||
"msc " CNLINK_NR_RANGE,
|
||||
"Configure an IuCS link to an MSC\n"
|
||||
"MSC nr\n")
|
||||
{
|
||||
return cnlink_nr(vty, &g_hnbgw->sccp.cnpool_iucs, argc, argv);
|
||||
}
|
||||
|
||||
/* 'sgsn 0' */
|
||||
DEFUN(cfg_sgsn_nr, cfg_sgsn_nr_cmd,
|
||||
"sgsn " CNLINK_NR_RANGE,
|
||||
"Configure an IuPS link to an SGSN\n"
|
||||
"SGSN nr\n")
|
||||
{
|
||||
return cnlink_nr(vty, &g_hnbgw->sccp.cnpool_iups, argc, argv);
|
||||
}
|
||||
|
||||
/* 'msc 0' / 'remote-addr my-msc' and
|
||||
* 'sgsn 0' / 'remote-addr my-sgsn'
|
||||
*/
|
||||
DEFUN(cfg_cnlink_remote_addr,
|
||||
cfg_cnlink_remote_addr_cmd,
|
||||
"remote-addr NAME",
|
||||
"SCCP address to send RANAP/SCCP to\n"
|
||||
"SCCP address book entry name (see 'cs7 instance' / 'sccp-address')\n")
|
||||
{
|
||||
struct hnbgw_cnlink *cnlink = vty->index;
|
||||
cnlink->vty.remote_addr_name = talloc_strdup(cnlink, argv[0]);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
#define APPLY_STR "Immediately use configuration modified via telnet VTY, and restart components as needed.\n"
|
||||
#define SCCP_RESTART_STR \
|
||||
" If 'remote-addr' changed, related SCCP links will be restarted, possibly dropping active UE contexts."
|
||||
#define IMPLICIT_ON_STARTUP_STR \
|
||||
" This is run implicitly on program startup, only useful to apply changes made later via telnet VTY."
|
||||
|
||||
DEFUN(cfg_cnlink_apply_sccp, cfg_cnlink_apply_sccp_cmd,
|
||||
"apply sccp",
|
||||
APPLY_STR
|
||||
"For telnet VTY: apply SCCP and NRI config changes made to this CN link in the running osmo-hnbgw process."
|
||||
SCCP_RESTART_STR IMPLICIT_ON_STARTUP_STR "\n")
|
||||
{
|
||||
struct hnbgw_cnlink *cnlink = vty->index;
|
||||
hnbgw_cnlink_start_or_restart(cnlink);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_config_apply_sccp, cfg_config_apply_sccp_cmd,
|
||||
"apply sccp",
|
||||
APPLY_STR
|
||||
"For telnet VTY: apply all SCCP and NRI config changes made to any CN pools and CN links in the running"
|
||||
" osmo-hnbgw process."
|
||||
SCCP_RESTART_STR IMPLICIT_ON_STARTUP_STR "\n")
|
||||
{
|
||||
struct hnbgw_cnpool *cnpool;
|
||||
|
||||
cnpool = &g_hnbgw->sccp.cnpool_iucs;
|
||||
hnbgw_cnpool_apply_cfg(cnpool);
|
||||
hnbgw_cnpool_cnlinks_start_or_restart(cnpool);
|
||||
|
||||
cnpool = &g_hnbgw->sccp.cnpool_iups;
|
||||
hnbgw_cnpool_apply_cfg(cnpool);
|
||||
hnbgw_cnpool_cnlinks_start_or_restart(cnpool);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -440,27 +552,31 @@ static int config_write_hnbgw_iuh(struct vty *vty)
|
|||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static int config_write_hnbgw_iucs(struct vty *vty)
|
||||
/* hnbgw
|
||||
* msc 0 } this part
|
||||
* sgsn 0 }
|
||||
*/
|
||||
static void _config_write_cnlink(struct vty *vty, struct hnbgw_cnpool *cnpool)
|
||||
{
|
||||
if (!g_hnbgw->config.iucs_remote_addr_name)
|
||||
return CMD_SUCCESS;
|
||||
struct hnbgw_cnlink *cnlink;
|
||||
|
||||
vty_out(vty, " iucs%s", VTY_NEWLINE);
|
||||
vty_out(vty, " remote-addr %s%s", g_hnbgw->config.iucs_remote_addr_name,
|
||||
VTY_NEWLINE);
|
||||
llist_for_each_entry(cnlink, &cnpool->cnlinks, entry) {
|
||||
vty_out(vty, "%s %d%s", cnpool->peer_name, cnlink->nr, VTY_NEWLINE);
|
||||
if (cnlink->vty.remote_addr_name)
|
||||
vty_out(vty, " remote-addr %s%s", cnlink->vty.remote_addr_name, VTY_NEWLINE);
|
||||
/* FUTURE: NRI config */
|
||||
}
|
||||
}
|
||||
|
||||
static int config_write_msc(struct vty *vty)
|
||||
{
|
||||
_config_write_cnlink(vty, &g_hnbgw->sccp.cnpool_iucs);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static int config_write_hnbgw_iups(struct vty *vty)
|
||||
static int config_write_sgsn(struct vty *vty)
|
||||
{
|
||||
if (!g_hnbgw->config.iups_remote_addr_name)
|
||||
return CMD_SUCCESS;
|
||||
|
||||
vty_out(vty, " iups%s", VTY_NEWLINE);
|
||||
vty_out(vty, " remote-addr %s%s", g_hnbgw->config.iups_remote_addr_name,
|
||||
VTY_NEWLINE);
|
||||
|
||||
_config_write_cnlink(vty, &g_hnbgw->sccp.cnpool_iups);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -477,6 +593,12 @@ static int config_write_hnbgw_pfcp(struct vty *vty)
|
|||
}
|
||||
#endif
|
||||
|
||||
static void install_cnlink_elements(int node)
|
||||
{
|
||||
install_element(node, &cfg_cnlink_remote_addr_cmd);
|
||||
install_element(node, &cfg_cnlink_apply_sccp_cmd);
|
||||
}
|
||||
|
||||
void hnbgw_vty_init(void)
|
||||
{
|
||||
install_element(CONFIG_NODE, &cfg_hnbgw_cmd);
|
||||
|
@ -494,14 +616,14 @@ void hnbgw_vty_init(void)
|
|||
install_element(IUH_NODE, &cfg_hnbgw_iuh_hnbap_allow_tmsi_cmd);
|
||||
|
||||
install_element(HNBGW_NODE, &cfg_hnbgw_iucs_cmd);
|
||||
install_node(&iucs_node, config_write_hnbgw_iucs);
|
||||
|
||||
install_element(IUCS_NODE, &cfg_hnbgw_iucs_remote_addr_cmd);
|
||||
install_node(&iucs_node, NULL);
|
||||
|
||||
install_element(HNBGW_NODE, &cfg_hnbgw_iups_cmd);
|
||||
install_node(&iups_node, config_write_hnbgw_iups);
|
||||
install_node(&iups_node, NULL);
|
||||
|
||||
install_element(IUPS_NODE, &cfg_hnbgw_iups_remote_addr_cmd);
|
||||
/* deprecated: 'remote-addr' outside of 'msc 123' redirects to 'msc 0' / same for 'sgsn' */
|
||||
install_element(IUCS_NODE, &cfg_hnbgw_cnpool_remote_addr_cmd);
|
||||
install_element(IUPS_NODE, &cfg_hnbgw_cnpool_remote_addr_cmd);
|
||||
|
||||
install_element_ve(&show_cnlink_cmd);
|
||||
install_element_ve(&show_hnb_cmd);
|
||||
|
@ -524,5 +646,16 @@ void hnbgw_vty_init(void)
|
|||
install_element(PFCP_NODE, &cfg_pfcp_remote_addr_cmd);
|
||||
#endif
|
||||
|
||||
install_element(CONFIG_NODE, &cfg_msc_nr_cmd);
|
||||
install_node(&msc_node, config_write_msc);
|
||||
install_cnlink_elements(MSC_NODE);
|
||||
|
||||
install_element(CONFIG_NODE, &cfg_sgsn_nr_cmd);
|
||||
install_node(&sgsn_node, config_write_sgsn);
|
||||
install_cnlink_elements(SGSN_NODE);
|
||||
|
||||
/* global 'apply sccp' command. There are two more on MSC_NODE and SGSN_NODE from install_cnlink_elements(). */
|
||||
install_element(CONFIG_NODE, &cfg_config_apply_sccp_cmd);
|
||||
|
||||
osmo_tdef_vty_groups_init(HNBGW_NODE, hnbgw_tdef_group);
|
||||
}
|
||||
|
|
|
@ -259,14 +259,6 @@ int main(int argc, char **argv)
|
|||
|
||||
ranap_set_log_area(DRANAP);
|
||||
|
||||
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);
|
||||
|
||||
OSMO_ASSERT(g_hnbgw->config.iuh_local_ip);
|
||||
|
@ -300,6 +292,9 @@ int main(int argc, char **argv)
|
|||
hnbgw_pfcp_init();
|
||||
#endif
|
||||
|
||||
hnbgw_cnpool_start(&g_hnbgw->sccp.cnpool_iucs);
|
||||
hnbgw_cnpool_start(&g_hnbgw->sccp.cnpool_iups);
|
||||
|
||||
if (hnbgw_cmdline_config.daemonize) {
|
||||
rc = osmo_daemonize();
|
||||
if (rc < 0) {
|
||||
|
|
|
@ -0,0 +1,194 @@
|
|||
OsmoHNBGW> enable
|
||||
OsmoHNBGW# configure terminal
|
||||
|
||||
OsmoHNBGW(config)# ### cnpool doc strings
|
||||
OsmoHNBGW(config)# hnbgw
|
||||
OsmoHNBGW(config-hnbgw)# list
|
||||
...
|
||||
iucs
|
||||
iups
|
||||
...
|
||||
OsmoHNBGW(config-hnbgw)# iucs?
|
||||
iucs Configure IuCS options
|
||||
OsmoHNBGW(config-hnbgw)# iups?
|
||||
iups Configure IuPS options
|
||||
|
||||
OsmoHNBGW(config-hnbgw)# exit
|
||||
|
||||
OsmoHNBGW(config)# msc?
|
||||
msc Configure an IuCS link to an MSC
|
||||
OsmoHNBGW(config)# msc ?
|
||||
<0-1000> MSC nr
|
||||
|
||||
OsmoHNBGW(config)# sgsn?
|
||||
sgsn Configure an IuPS link to an SGSN
|
||||
OsmoHNBGW(config)# sgsn ?
|
||||
<0-1000> SGSN nr
|
||||
|
||||
OsmoHNBGW(config)# ### The config file has no 'msc' or 'sgsn', so defaults have been set up
|
||||
OsmoHNBGW(config)# show running-config
|
||||
...
|
||||
msc 0
|
||||
sgsn 0
|
||||
...
|
||||
|
||||
OsmoHNBGW(config)# msc 1
|
||||
|
||||
OsmoHNBGW(config-msc)# list
|
||||
...
|
||||
remote-addr NAME
|
||||
apply sccp
|
||||
...
|
||||
|
||||
OsmoHNBGW(config-msc)# remote-addr?
|
||||
remote-addr SCCP address to send RANAP/SCCP to
|
||||
OsmoHNBGW(config-msc)# remote-addr ?
|
||||
NAME SCCP address book entry name (see 'cs7 instance' / 'sccp-address')
|
||||
|
||||
OsmoHNBGW(config-msc)# apply?
|
||||
apply Immediately use configuration modified via telnet VTY, and restart components as needed.
|
||||
OsmoHNBGW(config-msc)# apply ?
|
||||
sccp For telnet VTY: apply SCCP and NRI config changes made to this CN link in the running osmo-hnbgw process. If 'remote-addr' changed, related SCCP links will be restarted, possibly dropping active UE contexts. This is run implicitly on program startup, only useful to apply changes made later via telnet VTY.
|
||||
|
||||
OsmoHNBGW(config-msc)# exit
|
||||
|
||||
OsmoHNBGW(config)# sgsn 1
|
||||
|
||||
OsmoHNBGW(config-sgsn)# list
|
||||
...
|
||||
remote-addr NAME
|
||||
apply sccp
|
||||
...
|
||||
|
||||
OsmoHNBGW(config-sgsn)# remote-addr?
|
||||
remote-addr SCCP address to send RANAP/SCCP to
|
||||
OsmoHNBGW(config-sgsn)# remote-addr ?
|
||||
NAME SCCP address book entry name (see 'cs7 instance' / 'sccp-address')
|
||||
|
||||
OsmoHNBGW(config-sgsn)# apply?
|
||||
apply Immediately use configuration modified via telnet VTY, and restart components as needed.
|
||||
OsmoHNBGW(config-sgsn)# apply ?
|
||||
sccp For telnet VTY: apply SCCP and NRI config changes made to this CN link in the running osmo-hnbgw process. If 'remote-addr' changed, related SCCP links will be restarted, possibly dropping active UE contexts. This is run implicitly on program startup, only useful to apply changes made later via telnet VTY.
|
||||
|
||||
OsmoHNBGW(config-sgsn)# exit
|
||||
|
||||
OsmoHNBGW(config)# ### Just by entering the nodes above, 'msc 1' and 'sgsn 1' now exist
|
||||
OsmoHNBGW(config)# show running-config
|
||||
...
|
||||
msc 0
|
||||
msc 1
|
||||
sgsn 0
|
||||
sgsn 1
|
||||
...
|
||||
|
||||
OsmoHNBGW(config)# ### Add {msc,sgsn}x{2,3}
|
||||
|
||||
OsmoHNBGW(config)# msc 2
|
||||
OsmoHNBGW(config-msc)# remote-addr addr-msc2
|
||||
OsmoHNBGW(config-msc)# exit
|
||||
|
||||
OsmoHNBGW(config)# msc 3
|
||||
OsmoHNBGW(config-msc)# remote-addr addr-msc3
|
||||
OsmoHNBGW(config-msc)# exit
|
||||
|
||||
OsmoHNBGW(config)# sgsn 2
|
||||
OsmoHNBGW(config-sgsn)# remote-addr addr-sgsn2
|
||||
OsmoHNBGW(config-sgsn)# exit
|
||||
|
||||
OsmoHNBGW(config)# sgsn 3
|
||||
OsmoHNBGW(config-sgsn)# remote-addr addr-sgsn3
|
||||
OsmoHNBGW(config-sgsn)# exit
|
||||
|
||||
OsmoHNBGW(config)# show running-config
|
||||
...
|
||||
msc 0
|
||||
msc 1
|
||||
msc 2
|
||||
remote-addr addr-msc2
|
||||
msc 3
|
||||
remote-addr addr-msc3
|
||||
sgsn 0
|
||||
sgsn 1
|
||||
sgsn 2
|
||||
remote-addr addr-sgsn2
|
||||
sgsn 3
|
||||
remote-addr addr-sgsn3
|
||||
...
|
||||
|
||||
OsmoHNBGW(config)# ### Re-entering existing nodes works (does not create new ones)
|
||||
OsmoHNBGW(config)# msc 3
|
||||
OsmoHNBGW(config-msc)# remote-addr addr-msc4
|
||||
OsmoHNBGW(config-msc)# exit
|
||||
OsmoHNBGW(config)# sgsn 2
|
||||
OsmoHNBGW(config-sgsn)# remote-addr addr-sgsn4
|
||||
OsmoHNBGW(config-sgsn)# exit
|
||||
|
||||
OsmoHNBGW(config)# show running-config
|
||||
...
|
||||
msc 0
|
||||
msc 1
|
||||
msc 2
|
||||
remote-addr addr-msc2
|
||||
msc 3
|
||||
remote-addr addr-msc4
|
||||
sgsn 0
|
||||
sgsn 1
|
||||
sgsn 2
|
||||
remote-addr addr-sgsn4
|
||||
sgsn 3
|
||||
remote-addr addr-sgsn3
|
||||
...
|
||||
|
||||
OsmoHNBGW(config)# ### Legacy configuration {'iups','iucs'} / 'remote-addr' redirects to {'msc 0','sgsn 0'}:
|
||||
|
||||
OsmoHNBGW(config)# hnbgw
|
||||
OsmoHNBGW(config-hnbgw)# iucs
|
||||
OsmoHNBGW(config-hnbgw-iucs)# remote-addr?
|
||||
% There is no matched command.
|
||||
OsmoHNBGW(config-hnbgw-iucs)# remote-addr ?
|
||||
% There is no matched command.
|
||||
OsmoHNBGW(config-hnbgw-iucs)# remote-addr addr-msc0
|
||||
% Deprecated: instead of hnbgw/iucs/remote-addr, use 'msc 0'/remote-addr
|
||||
OsmoHNBGW(config-hnbgw-iucs)# exit
|
||||
|
||||
OsmoHNBGW(config-hnbgw)# iups
|
||||
OsmoHNBGW(config-hnbgw-iups)# remote-addr?
|
||||
% There is no matched command.
|
||||
OsmoHNBGW(config-hnbgw-iups)# remote-addr ?
|
||||
% There is no matched command.
|
||||
OsmoHNBGW(config-hnbgw-iups)# remote-addr addr-sgsn0
|
||||
% Deprecated: instead of hnbgw/iups/remote-addr, use 'sgsn 0'/remote-addr
|
||||
OsmoHNBGW(config-hnbgw-iups)# exit
|
||||
|
||||
OsmoHNBGW(config-hnbgw)# show running-config
|
||||
...
|
||||
hnbgw
|
||||
...
|
||||
msc 0
|
||||
remote-addr addr-msc0
|
||||
msc 1
|
||||
msc 2
|
||||
remote-addr addr-msc2
|
||||
msc 3
|
||||
remote-addr addr-msc4
|
||||
sgsn 0
|
||||
remote-addr addr-sgsn0
|
||||
sgsn 1
|
||||
sgsn 2
|
||||
remote-addr addr-sgsn4
|
||||
sgsn 3
|
||||
remote-addr addr-sgsn3
|
||||
...
|
||||
|
||||
|
||||
OsmoHNBGW(config-hnbgw)# ### placement of the new 'msc' and 'sgsn' nodes must be below 'pfcp' and 'mgw' nodes
|
||||
OsmoHNBGW(config-hnbgw)# show running-config
|
||||
...
|
||||
hnbgw
|
||||
... !msc
|
||||
iuh
|
||||
... !msc
|
||||
mgw 0
|
||||
...
|
||||
msc 0
|
||||
...
|
|
@ -39,8 +39,9 @@ hnbgw
|
|||
rnc-id 23
|
||||
log-prefix hnb-id
|
||||
iuh
|
||||
iucs
|
||||
remote-addr my-msc
|
||||
iups
|
||||
remote-addr my-sgsn
|
||||
...
|
||||
msc 0
|
||||
remote-addr my-msc
|
||||
sgsn 0
|
||||
remote-addr my-sgsn
|
||||
...
|
||||
|
|
|
@ -32,6 +32,8 @@ hnbgw
|
|||
rnc-id 23
|
||||
log-prefix hnb-id
|
||||
iuh
|
||||
iucs
|
||||
remote-addr my-msc
|
||||
...
|
||||
msc 0
|
||||
remote-addr my-msc
|
||||
sgsn 0
|
||||
... !remote-addr
|
||||
|
|
|
@ -32,6 +32,8 @@ hnbgw
|
|||
rnc-id 23
|
||||
log-prefix hnb-id
|
||||
iuh
|
||||
iups
|
||||
remote-addr my-sgsn
|
||||
...
|
||||
msc 0
|
||||
sgsn 0
|
||||
remote-addr my-sgsn
|
||||
...
|
||||
|
|
|
@ -50,8 +50,9 @@ hnbgw
|
|||
rnc-id 23
|
||||
log-prefix hnb-id
|
||||
iuh
|
||||
iucs
|
||||
remote-addr my-msc
|
||||
iups
|
||||
remote-addr my-sgsn
|
||||
...
|
||||
msc 0
|
||||
remote-addr my-msc
|
||||
sgsn 0
|
||||
remote-addr my-sgsn
|
||||
...
|
||||
|
|
Loading…
Reference in New Issue