Hello Neels Hofmeyr, Jenkins Builder,

I'd like you to reexamine a change.  Please visit

    https://gerrit.osmocom.org/3303

to look at the new patch set (#2).

sccp: make simple client configurable via VTY

The osmo_sccp_simple_client_on_ss7_id and osmo_sccp_simple_client
are not entirely configurable via VTY commands.

Add additional logic that checks for a still existing, valid
configuration. If no or an insufficient configuration is detected,
assume use the caller supplied parameters as standard configuration.

Change-Id: I293f3526ce6182dca74a169a23449dbc7af57c7c
---
M include/osmocom/sigtran/osmo_ss7.h
M src/osmo_ss7.c
M src/sccp_user.c
3 files changed, 153 insertions(+), 35 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/libosmo-sccp refs/changes/03/3303/2

diff --git a/include/osmocom/sigtran/osmo_ss7.h 
b/include/osmocom/sigtran/osmo_ss7.h
index 57a4e06..87ace4a 100644
--- a/include/osmocom/sigtran/osmo_ss7.h
+++ b/include/osmocom/sigtran/osmo_ss7.h
@@ -307,6 +307,8 @@
 osmo_ss7_as_find_by_rctx(struct osmo_ss7_instance *inst, uint32_t rctx);
 struct osmo_ss7_as *
 osmo_ss7_as_find_by_l_rk_id(struct osmo_ss7_instance *inst, uint32_t l_rk_id);
+struct osmo_ss7_as *osmo_ss7_as_find_by_proto(struct osmo_ss7_instance *inst,
+                                             enum osmo_ss7_asp_protocol proto);
 struct osmo_ss7_as *
 osmo_ss7_as_find_or_create(struct osmo_ss7_instance *inst, const char *name,
                          enum osmo_ss7_asp_protocol proto);
@@ -383,6 +385,9 @@
 
 struct osmo_ss7_asp *
 osmo_ss7_asp_find_by_name(struct osmo_ss7_instance *inst, const char *name);
+struct osmo_ss7_asp
+*osmo_ss7_asp_find_by_proto(struct osmo_ss7_as *as,
+                           enum osmo_ss7_asp_protocol proto);
 struct osmo_ss7_asp *
 osmo_ss7_asp_find_or_create(struct osmo_ss7_instance *inst, const char *name,
                            uint16_t remote_port, uint16_t local_port,
diff --git a/src/osmo_ss7.c b/src/osmo_ss7.c
index c13c588..eb5a4ef 100644
--- a/src/osmo_ss7.c
+++ b/src/osmo_ss7.c
@@ -833,6 +833,41 @@
        return NULL;
 }
 
+/*! \brief Find Application Server (AS) by given protocol.
+ *  \param[in] inst SS7 Instance on which we operate
+ *  \param[in] proto Protocol identifier that must match
+ *  \returns pointer to AS on success; NULL otherwise
+ *  If an AS has an ASP also matching the given protocol, that AS is preferred.
+ *  If there are multiple matches, return the first matching AS. */
+struct osmo_ss7_as *osmo_ss7_as_find_by_proto(struct osmo_ss7_instance *inst,
+                                             enum osmo_ss7_asp_protocol proto)
+{
+       struct osmo_ss7_as *as;
+       struct osmo_ss7_as *as_without_asp = NULL;
+
+       OSMO_ASSERT(ss7_initialized);
+
+       /* Loop through the list with AS and try to find one where the proto
+          matches up */
+       llist_for_each_entry(as, &inst->as_list, list) {
+               if (as->cfg.proto == proto) {
+
+                       /* Put down the first AS that matches the proto, just in
+                        * case we will not find any matching ASP */
+                       if (!as_without_asp)
+                               as_without_asp = as;
+
+                       /* Check if the candicate we have here has any suitable
+                        * ASP */
+                       if (osmo_ss7_asp_find_by_proto(as, proto))
+                               return as;
+               }
+       }
+
+       /* Return with the second best find, if there is any */
+       return as_without_asp;
+}
+
 /*! \brief Find or Create Application Server
  *  \param[in] inst SS7 Instance on which we operate
  *  \param[in] name Name of Application Server
@@ -1044,6 +1079,23 @@
        return NULL;
 }
 
+/*! \brief Find an ASP that matches the given protocol.
+ *  \param[in] as Application Server in which to look for \ref asp
+ *  \returns SS7 ASP in case a matching one is found; NULL otherwise */
+struct osmo_ss7_asp
+*osmo_ss7_asp_find_by_proto(struct osmo_ss7_as *as,
+                           enum osmo_ss7_asp_protocol proto)
+{
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(as->cfg.asps); i++) {
+               if (as->cfg.asps[i] && as->cfg.asps[i]->cfg.proto == proto)
+                       return as->cfg.asps[i];
+       }
+
+       return NULL;
+}
+
 struct osmo_ss7_asp *
 osmo_ss7_asp_find_or_create(struct osmo_ss7_instance *inst, const char *name,
                            uint16_t remote_port, uint16_t local_port,
diff --git a/src/sccp_user.c b/src/sccp_user.c
index b21a756..c9443a2 100644
--- a/src/sccp_user.c
+++ b/src/sccp_user.c
@@ -242,54 +242,113 @@
                                  int remote_port, const char *remote_ip)
 {
        struct osmo_ss7_instance *ss7;
+       bool ss7_created = false;
        struct osmo_ss7_as *as;
+       bool as_created = false;
        struct osmo_ss7_route *rt;
+       bool rt_created = false;
        struct osmo_ss7_asp *asp;
-       char *as_name, *asp_name;
+       bool asp_created = false;
+       char *as_name, *asp_name = NULL;
 
+       /* Choose default ports when the caller does not supply valid port
+        * numbers. */
        if (!remote_port || remote_port < 0)
                remote_port = osmo_ss7_asp_protocol_port(prot);
        if (local_port < 0)
                local_port = osmo_ss7_asp_protocol_port(prot);
 
-       /* allocate + initialize SS7 instance */
-       ss7 = osmo_ss7_instance_find_or_create(ctx, ss7_id);
+       /* Check if there is already an ss7 instance present under
+        * the given id. If not, we will create a new one. */
+       ss7 = osmo_ss7_instance_find(ss7_id);
        if (!ss7) {
-               LOGP(DLSCCP, LOGL_ERROR, "Failed to find or create SS7 
instance\n");
-               return NULL;
+               LOGP(DLSCCP, LOGL_NOTICE, "%s: Creating SS7 instance\n",
+                    name);
+
+               /* Create a new ss7 instance */
+               ss7 = osmo_ss7_instance_find_or_create(ctx, ss7_id);
+               if (!ss7) {
+                       LOGP(DLSCCP, LOGL_ERROR,
+                            "Failed to find or create SS7 instance\n");
+                       return NULL;
+               }
+
+               /* Setup primary pointcode
+                * NOTE: This means that the user must set the pointcode to a
+                * proper value when a cs7 instance is defined via the VTY. */
+               ss7->cfg.primary_pc = pc;
+               ss7_created = true;
        }
-       ss7->cfg.primary_pc = pc;
+       LOGP(DLSCCP, LOGL_NOTICE, "%s: Using SS7 instance %u, pc:%s\n", name,
+            ss7->cfg.id, osmo_ss7_pointcode_print(ss7, ss7->cfg.primary_pc));
 
-       as_name = talloc_asprintf(ctx, "as-clnt-%s", name);
-       asp_name = talloc_asprintf(ctx, "asp-clnt-%s", name);
+       /* There must not be an existing SCCP istance, regarless if the simple
+        * client has created the SS7 instance or if it was already present.
+        * An already existing SCCP instance would be an indication that this
+        * function has been called twice with the same SS7 instance, which
+        * must not be the case! */
+       OSMO_ASSERT(ss7->sccp == NULL);
 
-       /* application server */
-       as = osmo_ss7_as_find_or_create(ss7, as_name, prot);
-       if (!as)
-               goto out_strings;
+       /* Check if there is already an application server that matches
+        * the protocol we intend to use. If not, we will create one. */
+       as = osmo_ss7_as_find_by_proto(ss7, prot);
+       if (!as) {
+               LOGP(DLSCCP, LOGL_NOTICE, "%s: Creating AS instance\n",
+                    name);
+               as_name = talloc_asprintf(ctx, "as-clnt-%s", name);
+               as = osmo_ss7_as_find_or_create(ss7, as_name, prot);
+               talloc_free(as_name);
+               if (!as)
+                       goto out_ss7;
+               as_created = true;
 
-       as->cfg.routing_key.pc = pc;
+               as->cfg.routing_key.pc = ss7->cfg.primary_pc;
 
-       /* install default route */
-       rt = osmo_ss7_route_create(ss7->rtable_system, 0, 0, as_name);
-       if (!rt)
-               goto out_as;
-       talloc_free(as_name);
+               /* install default route */
+               rt = osmo_ss7_route_create(ss7->rtable_system, 0, 0,
+                                          as->cfg.name);
+               if (!rt)
+                       goto out_as;
+               rt_created = true;
+       }
+       LOGP(DLSCCP, LOGL_NOTICE, "%s: Using AS instance %s\n", name,
+            as->cfg.name);
 
-       /* application server process */
-       asp = osmo_ss7_asp_find_or_create(ss7, asp_name, remote_port, 
local_port,
-                                         prot);
-       if (!asp)
-               goto out_rt;
-       asp->cfg.local.host = talloc_strdup(asp, local_ip);
-       asp->cfg.remote.host = talloc_strdup(asp, remote_ip);
-       osmo_ss7_as_add_asp(as, asp_name);
+       /* Check if we do already have an application server process
+        * that is associated with the application server we have choosen
+        * the application server process must also match the protocol
+        * we intend to use. */
+       asp = osmo_ss7_asp_find_by_proto(as, prot);
+       if (!asp) {
+               LOGP(DLSCCP, LOGL_NOTICE, "%s: Creating ASP instance\n",
+                    name);
+               asp_name = talloc_asprintf(ctx, "asp-clnt-%s", name);
+               asp =
+                   osmo_ss7_asp_find_or_create(ss7, asp_name, remote_port,
+                                               local_port, prot);
+               talloc_free(asp_name);
+               if (!asp)
+                       goto out_rt;
+               asp_created = true;
+
+               asp->cfg.local.host = talloc_strdup(asp, local_ip);
+               asp->cfg.remote.host = talloc_strdup(asp, remote_ip);
+
+               osmo_ss7_as_add_asp(as, asp->cfg.name);
+       }
+
+       /* Ensure that the ASP we use is set to client mode. */
+       asp->cfg.is_server = false;
+
+       /* Restart ASP */
        if (prot != OSMO_SS7_ASP_PROT_IPA)
                osmo_ss7_asp_use_default_lm(asp, LOGL_DEBUG);
-       talloc_free(asp_name);
        osmo_ss7_asp_restart(asp);
+       LOGP(DLSCCP, LOGL_NOTICE, "%s: Using ASP instance %s\n", name,
+            asp->cfg.name);
 
-       /* Allocate SCCP stack + SCCP user */
+       /* Allocate SCCP instance */
+       LOGP(DLSCCP, LOGL_NOTICE, "%s: Creating SCCP instance\n", name);
        ss7->sccp = osmo_sccp_instance_create(ss7, NULL);
        if (!ss7->sccp)
                goto out_asp;
@@ -297,15 +356,17 @@
        return ss7->sccp;
 
 out_asp:
-       osmo_ss7_asp_destroy(asp);
+       if (asp_created)
+               osmo_ss7_asp_destroy(asp);
 out_rt:
-       osmo_ss7_route_destroy(rt);
+       if (rt_created)
+               osmo_ss7_route_destroy(rt);
 out_as:
-       osmo_ss7_as_destroy(as);
-out_strings:
-       talloc_free(as_name);
-       talloc_free(asp_name);
-       osmo_ss7_instance_destroy(ss7);
+       if (as_created)
+               osmo_ss7_as_destroy(as);
+out_ss7:
+       if (ss7_created)
+               osmo_ss7_instance_destroy(ss7);
 
        return NULL;
 }

-- 
To view, visit https://gerrit.osmocom.org/3303
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: newpatchset
Gerrit-Change-Id: I293f3526ce6182dca74a169a23449dbc7af57c7c
Gerrit-PatchSet: 2
Gerrit-Project: libosmo-sccp
Gerrit-Branch: master
Gerrit-Owner: dexter <[email protected]>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: Neels Hofmeyr <[email protected]>

Reply via email to