pespin has uploaded this change for review. ( 
https://gerrit.osmocom.org/c/osmo-bsc/+/34511?usp=email )


Change subject: sccplite: Support multiple MGW in MGW pool
......................................................................

sccplite: Support multiple MGW in MGW pool

Before this patch, the MGW was selected at startup, and the MGCP data
was always forwarded to that same MGW.
If several MGW were configured in the MGW pool, then osmo-bsc would
select any of those from the pool, and start configured the BTS-side
connection on an endpoint in that MGW. However, when the MSC submitted
the MGCP encapsulated in IPA to the BSC, the BSC would always forward
the MGCP message to that same MGW selected at startup.
As a result, multiple MGWs configured with osmo-bsc using SCCPlite was
broken.

This commit fixes support for multiple MGWs by looking up the already
selected MGW (to setup the BTS-side conn on the endpoint), based on the
CIC (MGCP Endpoint) which was provided by the MSC upon AssignReq.

Related: OS#6189
Depends: libosmocore.git Change-Id Iee361d740845257fa62c9093e30e8079fa933827
Depends: osmo-mgw.git Change-Id I18d7bdf650c0ec87ae16ed4944aed9f495400137
Change-Id: Ia106a21b7692eb5b2ac3b5ac2b358bedbc3b9da6
---
M TODO-RELEASE
M src/osmo-bsc/osmo_bsc_mgcp.c
M src/osmo-bsc/osmo_bsc_msc.c
3 files changed, 144 insertions(+), 19 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/osmo-bsc refs/changes/11/34511/1

diff --git a/TODO-RELEASE b/TODO-RELEASE
index d0852fc..7a7ec22 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
+libosmocore > 1.9.0   working (compiling) OSMO_SOCKADDR_STR_FMT_ARGS_NOT_NULL
diff --git a/src/osmo-bsc/osmo_bsc_mgcp.c b/src/osmo-bsc/osmo_bsc_mgcp.c
index 1b8e089..de11f44 100644
--- a/src/osmo-bsc/osmo_bsc_mgcp.c
+++ b/src/osmo-bsc/osmo_bsc_mgcp.c
@@ -2,6 +2,7 @@
  * SCCPlite MGCP handling
  *
  * (C) 2018 by Harald Welte <lafo...@gnumonks.org>
+ * (C) 2023 by sysmocom s.f.m.c. GmbH <i...@sysmocom.de>
  * All Rights Reserved
  *
  * This program is free software; you can redistribute it and/or modify
@@ -19,6 +20,15 @@
  *
  */

+#include <string.h>
+
+#include <osmocom/core/utils.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/socket.h>
+#include <osmocom/core/sockaddr_str.h>
+#include <osmocom/mgcp_client/mgcp_client_endpoint_fsm.h>
+#include <osmocom/mgcp_client/mgcp_client.h>
+
 #include <osmocom/bsc/bsc_msc_data.h>
 #include <osmocom/bsc/osmo_bsc.h>
 #include <osmocom/bsc/gsm_data.h>
@@ -46,22 +56,121 @@
        return osmo_msc_data_find(bsc_gsmnet, msc_nr);
 }

+/* negative on error, filled buf size upon success */
+static int parse_local_endpoint_name(char *buf, size_t buf_len, const char 
*data)
+{
+       char line[1024];
+       char *epstart, *sep;
+       const char *start = data;
+       char *eol = strpbrk(start, "\r\n");
+       if (!eol)
+               return -1;
+
+       if (eol - start > sizeof(line))
+               return -1;
+       memcpy(line, start, eol - start);
+       line[eol - start] = '\0';
+
+       if (!(epstart = strchr(line, ' ')))
+               return -1;
+       epstart++;
+       /* epstart now points to trans */
+
+       if (!(epstart = strchr(epstart, ' ')))
+               return -1;
+       epstart++;
+       /* epstart now points to endpoint */
+       if (!(sep = strchr(epstart, '@')))
+               return -1;
+       if (sep - epstart >= buf_len)
+               return -1;
+
+       *sep = '\0';
+       osmo_strlcpy(buf, epstart, buf_len);
+       return 0;
+}
+
 /* We received an IPA-encapsulated MGCP message from a MSC. Transfers msg 
ownership. */
 int bsc_sccplite_rx_mgcp(struct osmo_ss7_asp *asp, struct msgb *msg)
 {
        struct bsc_msc_data *msc;
+       struct gsm_subscriber_connection *conn;
+       char rcv_ep_local_name[1024];
+       struct osmo_sockaddr_str osa_str = {};
+       struct osmo_sockaddr osa = {};
+       socklen_t dest_len;
+       struct mgcp_client *mgcp_cli = NULL;
        int rc;

        LOGP(DMSC, LOGL_NOTICE, "%s: Received IPA-encapsulated MGCP: %s\n",
             osmo_ss7_asp_get_name(asp), msg->l2h);
-       msc = msc_from_asp(asp);
-       if (msc) {
-               /* we don't have a write queue here as we simply expect the 
socket buffers
-                * to be large enough to deal with whatever small/infrequent 
MGCP messages */
-               rc = send(msc->mgcp_ipa.ofd.fd, msgb_l2(msg), msgb_l2len(msg), 
0);
-       } else
-               rc = 0;

+       msc = msc_from_asp(asp);
+       if (!msc) {
+               rc = 0;
+               goto free_msg_ret;
+       }
+
+       rc = parse_local_endpoint_name(rcv_ep_local_name, 
sizeof(rcv_ep_local_name), (const char *)msg->l2h);
+       if (rc < 0) {
+               LOGP(DMSC, LOGL_ERROR, "(%s:) Received IPA-encapsulated MGCP: 
Failed to parse CIC\n",
+                    osmo_ss7_asp_get_name(asp));
+               goto free_msg_ret;
+       }
+
+       /* Lookup which conn attached to the MSC holds an MGW endpoint the same
+        * Endpoint Number as the one provided in the MGCP msg we received from
+        * MSC. Sine CIC are unique per MSC, that's the same MGW in the pool
+        * where we have to forward the MGCP message. */
+       llist_for_each_entry(conn, &bsc_gsmnet->subscr_conns, entry) {
+               const char *ep_local_name;
+               if (conn->sccp.msc != msc)
+                       continue; /* Only conns belonging to this MSC */
+               if (!conn->user_plane.mgw_endpoint)
+                       continue;
+               ep_local_name = 
osmo_mgcpc_ep_local_name(conn->user_plane.mgw_endpoint);
+               LOGPFSMSL(conn->fi, DMSC, LOGL_NOTICE, "ep_local_name='%s' vs 
rcv_ep_local_name='%s'\n", ep_local_name, rcv_ep_local_name);
+               if (!ep_local_name)
+                       continue;
+               if (strcmp(ep_local_name, rcv_ep_local_name) != 0)
+                       continue;
+               mgcp_cli = osmo_mgcpc_ep_client(conn->user_plane.mgw_endpoint);
+               if (!mgcp_cli)
+                       continue;
+               break;
+       }
+
+       if (!mgcp_cli) {
+               LOGP(DMSC, LOGL_ERROR, "(%s:) Received IPA-encapsulated MGCP: 
Failed to find associated MGW\n",
+                    osmo_ss7_asp_get_name(asp));
+               rc = 0;
+               goto free_msg_ret;
+       }
+
+       rc = osmo_sockaddr_str_from_str(&osa_str, 
mgcp_client_remote_addr_str(mgcp_cli),
+                                       mgcp_client_remote_port(mgcp_cli));
+       if (rc < 0) {
+               LOGP(DMSC, LOGL_ERROR, "(%s:) Received IPA-encapsulated MGCP: 
Failed to parse MGCP address %s:%u\n",
+                    osmo_ss7_asp_get_name(asp), 
mgcp_client_remote_addr_str(mgcp_cli), mgcp_client_remote_port(mgcp_cli));
+               goto free_msg_ret;
+       }
+
+       LOGP(DMSC, LOGL_NOTICE, "%s: Forwarding IPA-encapsulated MGCP to MGW at 
" OSMO_SOCKADDR_STR_FMT "\n",
+            osmo_ss7_asp_get_name(asp), 
OSMO_SOCKADDR_STR_FMT_ARGS_NOT_NULL(&osa_str));
+
+       rc = osmo_sockaddr_str_to_sockaddr(&osa_str, &osa.u.sas);
+       if (rc < 0) {
+               LOGP(DMSC, LOGL_ERROR, "(%s:) Received IPA-encapsulated MGCP: 
Failed to parse MGCP address " OSMO_SOCKADDR_STR_FMT "\n",
+                    osmo_ss7_asp_get_name(asp), 
OSMO_SOCKADDR_STR_FMT_ARGS_NOT_NULL(&osa_str));
+               goto free_msg_ret;
+       }
+       dest_len = osmo_sockaddr_size(&osa);
+
+       /* we don't have a write queue here as we simply expect the socket 
buffers
+               * to be large enough to deal with whatever small/infrequent 
MGCP messages */
+       rc = sendto(msc->mgcp_ipa.ofd.fd, msgb_l2(msg), msgb_l2len(msg), 0, 
&osa.u.sa, dest_len);
+
+free_msg_ret:
        msgb_free(msg);
        return rc;
 }
diff --git a/src/osmo-bsc/osmo_bsc_msc.c b/src/osmo-bsc/osmo_bsc_msc.c
index dfba2de..2425592 100644
--- a/src/osmo-bsc/osmo_bsc_msc.c
+++ b/src/osmo-bsc/osmo_bsc_msc.c
@@ -376,26 +376,15 @@

 int osmo_bsc_msc_init(struct bsc_msc_data *msc)
 {
-       struct gsm_network *net = msc->network;
-       struct mgcp_client *mgcp_cli;
        int rc;

        /* Everything below refers to SCCP-Lite MSC connections only. */
        if (msc_is_aoip(msc))
                return 0;

-       /* Note: MGW is preselected here at startup, which means currently
-        * osmo-bsc configured for SCCPLite doesn't support MGW pools with more
-        * than 1 MGW.
-        */
-       mgcp_cli = mgcp_client_pool_get(net->mgw.mgw_pool);
-       OSMO_ASSERT(mgcp_cli);
        rc = osmo_sock_init2_ofd(&msc->mgcp_ipa.ofd, AF_UNSPEC, SOCK_DGRAM, 
IPPROTO_UDP,
                                 msc->mgcp_ipa.local_addr, 
msc->mgcp_ipa.local_port,
-                                mgcp_client_remote_addr_str(mgcp_cli),
-                                mgcp_client_remote_port(mgcp_cli),
-                                OSMO_SOCK_F_BIND | OSMO_SOCK_F_CONNECT);
-       mgcp_client_pool_put(mgcp_cli);
+                                NULL, 0, OSMO_SOCK_F_BIND);
        if (rc < 0) {
                LOGP(DMSC, LOGL_ERROR, "msc %u: Could not create/connect/bind 
MGCP proxy socket: %d\n",
                        msc->nr, rc);

--
To view, visit https://gerrit.osmocom.org/c/osmo-bsc/+/34511?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-bsc
Gerrit-Branch: master
Gerrit-Change-Id: Ia106a21b7692eb5b2ac3b5ac2b358bedbc3b9da6
Gerrit-Change-Number: 34511
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <pes...@sysmocom.de>
Gerrit-MessageType: newchange

Reply via email to