pespin has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-hnbgw/+/40627?usp=email )
Change subject: Make sure MSC/SGSN PC are added to sccp-addressbook ......................................................................
Make sure MSC/SGSN PC are added to sccp-addressbook
This way they can used by libosmo-sigtran to figure out interesting remote PCs it should track availability for.
Related: OS#5917 Related: SYS#7501 Depends: libosmo-sigtran.git Change-Id I9d2452d9cc8e443050927a047b7ebacd2b2f37e1 Change-Id: I6a537adca27dd2bbad33d0f2be71eb41d6ad3a27 --- M TODO-RELEASE M include/osmocom/hnbgw/hnbgw.h M include/osmocom/hnbgw/hnbgw_cn.h M src/osmo-hnbgw/cnlink.c M src/osmo-hnbgw/hnbgw_cn.c M tests/cnpool.vty 6 files changed, 131 insertions(+), 77 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-hnbgw refs/changes/27/40627/1
diff --git a/TODO-RELEASE b/TODO-RELEASE index 0ed7189..895cb3c 100644 --- a/TODO-RELEASE +++ b/TODO-RELEASE @@ -7,3 +7,4 @@ # If any interfaces have been added since the last public release: c:r:a + 1. # If any interfaces have been removed or changed since the last public release: c:r:0. #library what description / commit summary line +libosmo-sigtran >2.1.0 osmo_sccp_addr_{create,update}() diff --git a/include/osmocom/hnbgw/hnbgw.h b/include/osmocom/hnbgw/hnbgw.h index 685bc12..f4ec21c 100644 --- a/include/osmocom/hnbgw/hnbgw.h +++ b/include/osmocom/hnbgw/hnbgw.h @@ -56,6 +56,8 @@ #define DEFAULT_PC_HNBGW ((23 << 3) + 5) #define DEFAULT_PC_MSC ((23 << 3) + 1) #define DEFAULT_PC_SGSN ((23 << 3) + 4) +#define DEFAULT_ADDR_NAME_MSC "addr-dyn-msc-default" +#define DEFAULT_ADDR_NAME_SGSN "addr-dyn-sgsn-default"
/* 25.467 Section 7.1 */ #define IUH_DEFAULT_SCTP_PORT 29169 diff --git a/include/osmocom/hnbgw/hnbgw_cn.h b/include/osmocom/hnbgw/hnbgw_cn.h index 8e765c8..68a0ac5 100644 --- a/include/osmocom/hnbgw/hnbgw_cn.h +++ b/include/osmocom/hnbgw/hnbgw_cn.h @@ -37,6 +37,7 @@ 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; + const char *default_addr_name;
struct hnbgw_cnpool_cfg vty; struct hnbgw_cnpool_cfg use; diff --git a/src/osmo-hnbgw/cnlink.c b/src/osmo-hnbgw/cnlink.c index ea53ee0..83ca51f 100644 --- a/src/osmo-hnbgw/cnlink.c +++ b/src/osmo-hnbgw/cnlink.c @@ -385,45 +385,22 @@ return hnbgw_cnlink_tx_sccp_unitdata_req(cnlink, msg); }
-static bool addr_has_pc_and_ssn(const struct osmo_sccp_addr *addr) +/* Return address found in sccp address-book, and fill in missing fields in the + * entry with default values. */ +static struct osmo_ss7_instance *sccp_addr_by_name_filled(struct osmo_sccp_addr *dest, const char *addr_name, uint32_t default_pc) { - if (!(addr->presence & OSMO_SCCP_ADDR_T_SSN)) - return false; - if (!(addr->presence & OSMO_SCCP_ADDR_T_PC)) - return false; - return true; -} + struct osmo_ss7_instance *s7i; + s7i = osmo_sccp_addr_by_name(dest, addr_name); + if (!s7i) + return NULL;
-static int resolve_addr_name(struct osmo_sccp_addr *dest, struct osmo_ss7_instance **ss7, - const char *addr_name, const char *label, - uint32_t default_pc) -{ - if (!addr_name) { + /* Address exists in address-book but may not be filled entirely: */ + if (!dest->presence) osmo_sccp_make_addr_pc_ssn(dest, default_pc, OSMO_SCCP_SSN_RANAP); - if (label) - LOGP(DCN, LOGL_INFO, "%s remote addr not configured, using default: %s\n", label, - osmo_sccp_addr_name(*ss7, dest)); - return 0; - } + else if (!(dest->presence & OSMO_SCCP_ADDR_T_SSN)) + osmo_sccp_addr_set_ssn(dest, OSMO_SCCP_SSN_RANAP);
- *ss7 = osmo_sccp_addr_by_name(dest, addr_name); - if (!*ss7) { - if (label) - LOGP(DCN, 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)) { - if (label) - LOGP(DCN, LOGL_ERROR, "Invalid/incomplete %s remote-addr: %s\n", - label, osmo_sccp_addr_name(*ss7, dest)); - return -1; - } - - return 0; + return s7i; }
char *hnbgw_cnlink_sccp_addr_to_str(struct hnbgw_cnlink *cnlink, const struct osmo_sccp_addr *addr) @@ -451,13 +428,17 @@ bool changed = false;
if (cnlink->vty.remote_addr_name && cnlink->use.remote_addr_name) { - struct osmo_ss7_instance *ss7; + struct osmo_ss7_instance *s7i; 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, cnlink->pool->default_remote_pc); - if (osmo_sccp_addr_cmp(&remote_addr, &cnlink->remote_addr, OSMO_SCCP_ADDR_T_PC | OSMO_SCCP_ADDR_T_SSN)) + s7i = sccp_addr_by_name_filled(&remote_addr, cnlink->vty.remote_addr_name, + cnlink->pool->default_remote_pc); + if (!s7i) + return true; + 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. */ @@ -465,7 +446,6 @@ }
/* if more cnlink configuration is added in the future, it needs to be compared here. */ - return changed; }
@@ -485,19 +465,20 @@ * Set cnlink->hnbgw_sccp_user to the new SCCP instance. Return 0 on success, negative on error. */ int hnbgw_cnlink_start_or_restart(struct hnbgw_cnlink *cnlink) { - struct osmo_ss7_instance *ss7 = NULL; + struct osmo_ss7_instance *s7i = NULL; struct hnbgw_sccp_user *hsu; + uint32_t ss7_id; + int rc;
/* If a hnbgw_sccp_user has already been set up, use that. */ if (cnlink->hnbgw_sccp_user) { - if (hnbgw_cnlink_sccp_cfg_changed(cnlink)) { - LOG_CNLINK(cnlink, DCN, LOGL_NOTICE, "config changed, restarting SCCP\n"); - hnbgw_cnlink_drop_sccp(cnlink); - } else { + if (!hnbgw_cnlink_sccp_cfg_changed(cnlink)) { 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_NOTICE, "config changed, restarting SCCP\n"); + hnbgw_cnlink_drop_sccp(cnlink); } else { LOG_CNLINK(cnlink, DCN, LOGL_DEBUG, "no SCCP instance selected yet\n"); } @@ -505,49 +486,64 @@ /* 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->use.remote_addr_name) { - if (resolve_addr_name(&cnlink->remote_addr, &ss7, cnlink->use.remote_addr_name, cnlink->name, - cnlink->pool->default_remote_pc)) { + if (!cnlink->use.remote_addr_name) { + /* No remote address configured in VTY, set a default one and + * make sure it becomes registered in the sccp address-book: */ + cnlink->use.remote_addr_name = talloc_strdup(cnlink, cnlink->pool->default_addr_name); + s7i = osmo_sccp_addr_by_name(&cnlink->remote_addr, cnlink->use.remote_addr_name); + if (!s7i) { + LOG_CNLINK(cnlink, DCN, LOGL_NOTICE, "To auto-configure cnlink, creating cs7 instance 0 implicitly\n"); + s7i = osmo_ss7_instance_find_or_create(g_hnbgw, 0); + OSMO_ASSERT(s7i); + osmo_sccp_make_addr_pc_ssn(&cnlink->remote_addr, + cnlink->pool->default_remote_pc, + OSMO_SCCP_SSN_RANAP); + rc = osmo_sccp_addr_create(s7i, cnlink->use.remote_addr_name, &cnlink->remote_addr); + if (rc < 0) { + LOG_CNLINK(cnlink, DCN, LOGL_ERROR, "Failed adding address '%s' to sccp address-book!\n", + cnlink->use.remote_addr_name); + return -EINVAL; + } + } + /* Update VTY config to show & point to the address dynamically added to address-book: */ + cnlink->vty.remote_addr_name = talloc_strdup(cnlink, cnlink->use.remote_addr_name); + } else { + s7i = sccp_addr_by_name_filled(&cnlink->remote_addr, cnlink->use.remote_addr_name, cnlink->pool->default_remote_pc); + if (!s7i) { LOG_CNLINK(cnlink, DCN, LOGL_ERROR, "cannot initialize SCCP: there is no SCCP address named '%s'\n", cnlink->use.remote_addr_name); return -ENOENT; } - LOG_CNLINK(cnlink, DCN, LOGL_DEBUG, "remote-addr is '%s', using cs7 instance %u\n", - cnlink->use.remote_addr_name, osmo_ss7_instance_get_id(ss7)); - } else { - /* If no address is configured, use the default remote CN address, according to legacy behavior. */ - 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. - * If it doesn't exist, it will get created by osmo_sccp_simple_client_on_ss7_id(). */ - if (!ss7) { - 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 (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; - LOG_CNLINK(cnlink, DCN, LOGL_DEBUG, "using existing SCCP instance %s on cs7 instance %u\n", - hsu->name, osmo_ss7_instance_get_id(ss7)); - cnlink->hnbgw_sccp_user = hsu; - hnbgw_sccp_user_get(cnlink->hnbgw_sccp_user, HSU_USE_CNLINK); - hnbgw_cnlink_log_self(cnlink); - return 0; + cnlink->use.remote_addr_name, osmo_ss7_instance_get_id(s7i)); + /* Address exists in address-book but may not be filled entirely: */ + rc = osmo_sccp_addr_update(s7i, cnlink->use.remote_addr_name, &cnlink->remote_addr); + if (rc < 0) { + LOG_CNLINK(cnlink, DCN, LOGL_ERROR, "Failed updating address '%s' in sccp address-book!\n", + cnlink->use.remote_addr_name); + return -EINVAL; } - /* else cnlink->hnbgw_sccp_user stays NULL and is set up below. */ - LOG_CNLINK(cnlink, DCN, LOGL_DEBUG, "cs7 instance %u has no configured SCCP instance yet\n", osmo_ss7_instance_get_id(ss7)); }
+ ss7_id = osmo_ss7_instance_get_id(s7i); + + /* Has another cnlink already set up an SCCP instance for this s7i? */ + llist_for_each_entry(hsu, &g_hnbgw->sccp.users, entry) { + if (hsu->ss7 != s7i) + continue; + LOG_CNLINK(cnlink, DCN, LOGL_DEBUG, "using existing SCCP instance %s on cs7 instance %u\n", + hsu->name, ss7_id); + cnlink->hnbgw_sccp_user = hsu; + hnbgw_sccp_user_get(cnlink->hnbgw_sccp_user, HSU_USE_CNLINK); + hnbgw_cnlink_log_self(cnlink); + 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 configured SCCP instance yet\n", ss7_id); + /* 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'. */ - cnlink->hnbgw_sccp_user = hnbgw_sccp_user_alloc(ss7 ? osmo_ss7_instance_get_id(ss7) : 0); + cnlink->hnbgw_sccp_user = hnbgw_sccp_user_alloc(ss7_id); hnbgw_sccp_user_get(cnlink->hnbgw_sccp_user, HSU_USE_CNLINK); hnbgw_cnlink_log_self(cnlink); return 0; diff --git a/src/osmo-hnbgw/hnbgw_cn.c b/src/osmo-hnbgw/hnbgw_cn.c index f881dc1..ab800f7 100644 --- a/src/osmo-hnbgw/hnbgw_cn.c +++ b/src/osmo-hnbgw/hnbgw_cn.c @@ -312,12 +312,14 @@ cnpool->pool_name = "iucs"; cnpool->peer_name = "msc"; cnpool->default_remote_pc = DEFAULT_PC_MSC; + cnpool->default_addr_name = DEFAULT_ADDR_NAME_MSC; cnpool->ctrs = rate_ctr_group_alloc(cnpool, &iucs_ctrg_desc, 0); break; case DOMAIN_PS: cnpool->pool_name = "iups"; cnpool->peer_name = "sgsn"; cnpool->default_remote_pc = DEFAULT_PC_SGSN; + cnpool->default_addr_name = DEFAULT_ADDR_NAME_SGSN; cnpool->ctrs = rate_ctr_group_alloc(cnpool, &iups_ctrg_desc, 0); break; default: diff --git a/tests/cnpool.vty b/tests/cnpool.vty index 78f660f..83d7352 100644 --- a/tests/cnpool.vty +++ b/tests/cnpool.vty @@ -134,10 +134,23 @@ OsmoHNBGW(config)# ### The config file has no 'msc' or 'sgsn', so defaults have been set up OsmoHNBGW(config)# show running-config ... +cs7 instance 0 + point-code 0.23.5 +... + sccp-address addr-dyn-msc-default + routing-indicator PC + point-code 0.23.1 + subsystem-number 142 + sccp-address addr-dyn-sgsn-default + routing-indicator PC + point-code 0.23.4 +... msc 0 name msc-0 + remote-addr addr-dyn-msc-default sgsn 0 name sgsn-0 + remote-addr addr-dyn-sgsn-default ...
OsmoHNBGW(config)# msc 1 @@ -227,10 +240,12 @@ ... msc 0 name msc-0 + remote-addr addr-dyn-msc-default msc 1 name msc-1 sgsn 0 name sgsn-0 + remote-addr addr-dyn-sgsn-default sgsn 1 name sgsn-1 ... @@ -259,6 +274,7 @@ ... msc 0 name msc-0 + remote-addr addr-dyn-msc-default msc 1 name msc-1 msc 2 @@ -271,6 +287,7 @@ allow-emergency sgsn 0 name sgsn-0 + remote-addr addr-dyn-sgsn-default sgsn 1 name sgsn-1 sgsn 2 @@ -297,6 +314,7 @@ ... msc 0 name msc-0 + remote-addr addr-dyn-msc-default msc 1 name msc-1 msc 2 @@ -307,6 +325,7 @@ remote-addr addr-msc4 sgsn 0 name sgsn-0 + remote-addr addr-dyn-sgsn-default sgsn 1 name sgsn-1 sgsn 2 @@ -378,3 +397,36 @@ ... msc 0 ... + +OsmoHNBGW(config-hnbgw)# exit +OsmoHNBGW(config)# ### Apply all SCCP changes: +OsmoHNBGW(config)# apply sccp +OsmoHNBGW(config)# show running-config +... +hnbgw +... +msc 0 + name msc-0 + remote-addr addr-msc0 +msc 1 + name msc-1 + remote-addr addr-dyn-msc-default +msc 2 + name msc-2 + remote-addr addr-msc2 +msc 3 + name msc-3 + remote-addr addr-msc4 +sgsn 0 + name sgsn-0 + remote-addr addr-sgsn0 +sgsn 1 + name sgsn-1 + remote-addr addr-dyn-sgsn-default +sgsn 2 + name sgsn-2 + remote-addr addr-sgsn4 +sgsn 3 + name sgsn-3 + remote-addr addr-sgsn3 +...