<p>dexter <strong>submitted</strong> this change.</p><p><a href="https://gerrit.osmocom.org/c/osmo-bsc/+/25123">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  laforge: Looks good to me, approved
  pespin: Looks good to me, but someone else must approve
  osmith: Looks good to me, but someone else must approve
  Jenkins Builder: Verified

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">osmo_bsc_main: integrate MGW pooling into osmo-bsc<br><br>Since the libosmo-mgcp-client now supports MGW pooling, lets use this<br>feature in osmo-bsc. Large RAN installations may benefit from<br>distributing the RTP voice stream load on multiple media gateways.<br><br>Depends: osmo-mgw Icaaba0e470e916eefddfee750b83f5f65291a6b0<br>Change-Id: I8f33ab2cea04b545c403a6fe479aa963a0fc0d0d<br>Related: SYS#5091<br>---<br>A doc/manuals/chapters/mgwpool.adoc<br>M doc/manuals/chapters/running.adoc<br>M doc/manuals/osmobsc-usermanual.adoc<br>M include/osmocom/bsc/gsm_data.h<br>M include/osmocom/bsc/vty.h<br>M src/osmo-bsc/bsc_subscr_conn_fsm.c<br>M src/osmo-bsc/bsc_vty.c<br>M src/osmo-bsc/osmo_bsc_main.c<br>M tests/handover/handover_test.c<br>9 files changed, 330 insertions(+), 18 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/doc/manuals/chapters/mgwpool.adoc b/doc/manuals/chapters/mgwpool.adoc</span><br><span>new file mode 100644</span><br><span>index 0000000..7d9e9a6</span><br><span>--- /dev/null</span><br><span>+++ b/doc/manuals/chapters/mgwpool.adoc</span><br><span>@@ -0,0 +1,243 @@</span><br><span style="color: hsl(120, 100%, 40%);">+[[mgw_pooling]]</span><br><span style="color: hsl(120, 100%, 40%);">+== MGW Pooling</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+OsmoBSC is able to use a pool of media gateway (MGW) instances since mid 2021.</span><br><span style="color: hsl(120, 100%, 40%);">+The aim of MGW pooling is to evenly distribute the RTP voice stream load across</span><br><span style="color: hsl(120, 100%, 40%);">+multiple MGW instances. This can help to scale out over multiple VMs or physical</span><br><span style="color: hsl(120, 100%, 40%);">+machines. Until osmo-mgw includes multithreading support, it may also be used to</span><br><span style="color: hsl(120, 100%, 40%);">+scale-out to multiple cores on a single host.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+The load distribution is managed in such a way that when a new call is placed,</span><br><span style="color: hsl(120, 100%, 40%);">+the pool will automatically assign the call to the MGW with the lowest load.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+MGW pooling is recommended for larger RAN installations. For small networks and</span><br><span style="color: hsl(120, 100%, 40%);">+lab installations the classic method with one MGW per BSC offers sufficient</span><br><span style="color: hsl(120, 100%, 40%);">+performance.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+=== VTY configuration</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+In OsmoBSC the MGW is controlled via an MGCP-Client. The VTY commands to</span><br><span style="color: hsl(120, 100%, 40%);">+configure the MGCP-Client are part of the 'msc' node due to historical reasons.</span><br><span style="color: hsl(120, 100%, 40%);">+Unfortunately this concept does not allow to configure multiple MGCP-Client</span><br><span style="color: hsl(120, 100%, 40%);">+instances as required by MGW pooling. In order to support MGW pooling a new</span><br><span style="color: hsl(120, 100%, 40%);">+'mgw' node has been added under the 'network' node.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+=== Existing configuration files</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Existing OsmoBSC configuration files will continue to work, but as soon as an</span><br><span style="color: hsl(120, 100%, 40%);">+MGW pool is configured the 'mgw' settings under the 'msc' node will be ignored.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Example configuration with only one MGCP-Client under the 'msc' node:</span><br><span style="color: hsl(120, 100%, 40%);">+----</span><br><span style="color: hsl(120, 100%, 40%);">+msc 0</span><br><span style="color: hsl(120, 100%, 40%);">+ mgw remote-ip 127.0.0.1</span><br><span style="color: hsl(120, 100%, 40%);">+ mgw remote-port 2428</span><br><span style="color: hsl(120, 100%, 40%);">+----</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+=== MGW pool configuration</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+To setup an MGW pool, the user must first install multiple OsmoMGW instances, so</span><br><span style="color: hsl(120, 100%, 40%);">+that they won’t interfere with each other. This can be done using different</span><br><span style="color: hsl(120, 100%, 40%);">+local host IP addresses or different ports. When OsmoMGW is installed from</span><br><span style="color: hsl(120, 100%, 40%);">+packages, the systemd configuration may also require adjustment.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+The VTY settings under the 'mgw' node works the same way as the VTY settings for</span><br><span style="color: hsl(120, 100%, 40%);">+the MGW under the 'msc' node.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Example configuration with two MGCP-Client instances in a pool:</span><br><span style="color: hsl(120, 100%, 40%);">+----</span><br><span style="color: hsl(120, 100%, 40%);">+ mgw 0</span><br><span style="color: hsl(120, 100%, 40%);">+  mgw remote-ip 127.0.0.1</span><br><span style="color: hsl(120, 100%, 40%);">+  mgw remote-port 2432</span><br><span style="color: hsl(120, 100%, 40%);">+  mgw local-ip 127.0.0.1</span><br><span style="color: hsl(120, 100%, 40%);">+  mgw local-port 2431</span><br><span style="color: hsl(120, 100%, 40%);">+  mgw endpoint-domain mgw0 <1></span><br><span style="color: hsl(120, 100%, 40%);">+ mgw 1</span><br><span style="color: hsl(120, 100%, 40%);">+  mgw remote-ip 127.0.0.1</span><br><span style="color: hsl(120, 100%, 40%);">+  mgw remote-port 2430</span><br><span style="color: hsl(120, 100%, 40%);">+  mgw local-ip 127.0.0.1</span><br><span style="color: hsl(120, 100%, 40%);">+  mgw local-port 2429</span><br><span style="color: hsl(120, 100%, 40%);">+  mgw endpoint-domain mgw1 <1></span><br><span style="color: hsl(120, 100%, 40%);">+----</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+<1> When working with multiple MGW / MGCP-Client instances, the domain name for</span><br><span style="color: hsl(120, 100%, 40%);">+each MGW should be different. Otherwise it won't be possible to distinguish the</span><br><span style="color: hsl(120, 100%, 40%);">+endpoint names in the log. It should also be noted that the domain name must</span><br><span style="color: hsl(120, 100%, 40%);">+match the configuration of the related OsmoMGW instance.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+=== MGW pool management</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+While it was not possible to change the MGCP-Client configuration under the</span><br><span style="color: hsl(120, 100%, 40%);">+“msc” node at runtime, the pool is fully runtime-manageable. The only limitation</span><br><span style="color: hsl(120, 100%, 40%);">+is that an MGCP-Client can not be restarted or removed as long as it is serving</span><br><span style="color: hsl(120, 100%, 40%);">+calls (see also: <<mgw_pooling_blocking>>).</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+==== MGW pool status</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+The VTY implements a 'show mgw-pool' command that lists the currently configured</span><br><span style="color: hsl(120, 100%, 40%);">+MGW pool members, their status and call utilization.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+----</span><br><span style="color: hsl(120, 100%, 40%);">+OsmoBSC> show mgw-pool</span><br><span style="color: hsl(120, 100%, 40%);">+% MGW-Pool:</span><br><span style="color: hsl(120, 100%, 40%);">+%  MGW 0</span><br><span style="color: hsl(120, 100%, 40%);">+%   mgcp-client:   connected</span><br><span style="color: hsl(120, 100%, 40%);">+%   service:       unblocked</span><br><span style="color: hsl(120, 100%, 40%);">+%   ongoing calls: 1</span><br><span style="color: hsl(120, 100%, 40%);">+%  MGW 1</span><br><span style="color: hsl(120, 100%, 40%);">+%   mgcp-client:   connected</span><br><span style="color: hsl(120, 100%, 40%);">+%   service:       unblocked</span><br><span style="color: hsl(120, 100%, 40%);">+%   ongoing calls: 0</span><br><span style="color: hsl(120, 100%, 40%);">+----</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+==== Adding an MGW / MGCP-Client to the MGW pool</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+To add a new MGCP-Client to the pool, the 'mgw' node is used. Like with the</span><br><span style="color: hsl(120, 100%, 40%);">+'bts' or the 'msc' node a reference number is used that usually starts at 0.</span><br><span style="color: hsl(120, 100%, 40%);">+However it is still possible to assign any number from 0-255. The enumeration</span><br><span style="color: hsl(120, 100%, 40%);">+also may contain gaps.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+----</span><br><span style="color: hsl(120, 100%, 40%);">+OsmoBSC> enable</span><br><span style="color: hsl(120, 100%, 40%);">+OsmoBSC# configure terminal</span><br><span style="color: hsl(120, 100%, 40%);">+OsmoBSC(config)# network</span><br><span style="color: hsl(120, 100%, 40%);">+OsmoBSC(config-net)# mgw 2</span><br><span style="color: hsl(120, 100%, 40%);">+OsmoBSC(config-mgw)# mgw</span><br><span style="color: hsl(120, 100%, 40%);">+  local-ip         local bind to connect to MGW from</span><br><span style="color: hsl(120, 100%, 40%);">+  local-port       local port to connect to MGW from</span><br><span style="color: hsl(120, 100%, 40%);">+  remote-ip        remote IP address to reach the MGW at</span><br><span style="color: hsl(120, 100%, 40%);">+  remote-port      remote port to reach the MGW at</span><br><span style="color: hsl(120, 100%, 40%);">+  endpoint-domain  Set the domain name to send in MGCP messages, e.g. the part 'foo' in 'rtpbridge/*@foo'.</span><br><span style="color: hsl(120, 100%, 40%);">+  reset-endpoint   Add an endpoint name that should be reset (DLCX) on connect to the reset-endpoint list,e.g. 'rtpbridge/*'</span><br><span style="color: hsl(120, 100%, 40%);">+----</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+The newly added MGW will immediately appear in the mgw-pool list but it won't</span><br><span style="color: hsl(120, 100%, 40%);">+be used until its configuration finished by reconnecting it.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+----</span><br><span style="color: hsl(120, 100%, 40%);">+% MGW-Pool:</span><br><span style="color: hsl(120, 100%, 40%);">+%  MGW 0</span><br><span style="color: hsl(120, 100%, 40%);">+%   mgcp-client:   connected</span><br><span style="color: hsl(120, 100%, 40%);">+%   service:       unblocked</span><br><span style="color: hsl(120, 100%, 40%);">+%   ongoing calls: 2</span><br><span style="color: hsl(120, 100%, 40%);">+%  MGW 1</span><br><span style="color: hsl(120, 100%, 40%);">+%   mgcp-client:   connected</span><br><span style="color: hsl(120, 100%, 40%);">+%   service:       unblocked</span><br><span style="color: hsl(120, 100%, 40%);">+%   ongoing calls: 3</span><br><span style="color: hsl(120, 100%, 40%);">+%  MGW 2</span><br><span style="color: hsl(120, 100%, 40%);">+%   mgcp-client:   disconnected</span><br><span style="color: hsl(120, 100%, 40%);">+%   service:       unblocked</span><br><span style="color: hsl(120, 100%, 40%);">+%   ongoing calls: 0</span><br><span style="color: hsl(120, 100%, 40%);">+----</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+==== Reconnecting an MGW / MGCP-Client</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+It may become necessary to reconnect an MGCP-Client. This is the case when the</span><br><span style="color: hsl(120, 100%, 40%);">+VTY configuration was changed at runtime. In order to make the changes effective</span><br><span style="color: hsl(120, 100%, 40%);">+the MGW configuration must be reloaded by reconnecting the MGW connection. Also</span><br><span style="color: hsl(120, 100%, 40%);">+newly created MGW instances require a reconnect once their configuration is</span><br><span style="color: hsl(120, 100%, 40%);">+done.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+To reconnect an MGCP-Client use the 'reconnect' VTY command:</span><br><span style="color: hsl(120, 100%, 40%);">+----</span><br><span style="color: hsl(120, 100%, 40%);">+OsmoBSC# mgw 2 reconnect</span><br><span style="color: hsl(120, 100%, 40%);">+----</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+The mgcp-client status should immediately change to 'connected'. The MGW is now</span><br><span style="color: hsl(120, 100%, 40%);">+ready to be used for new calls.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+----</span><br><span style="color: hsl(120, 100%, 40%);">+OsmoBSC# show mgw-pool</span><br><span style="color: hsl(120, 100%, 40%);">+% MGW-Pool:</span><br><span style="color: hsl(120, 100%, 40%);">+%  MGW 0</span><br><span style="color: hsl(120, 100%, 40%);">+%   mgcp-client:   connected</span><br><span style="color: hsl(120, 100%, 40%);">+%   service:       unblocked</span><br><span style="color: hsl(120, 100%, 40%);">+%   ongoing calls: 2</span><br><span style="color: hsl(120, 100%, 40%);">+%  MGW 1</span><br><span style="color: hsl(120, 100%, 40%);">+%   mgcp-client:   connected</span><br><span style="color: hsl(120, 100%, 40%);">+%   service:       unblocked</span><br><span style="color: hsl(120, 100%, 40%);">+%   ongoing calls: 3</span><br><span style="color: hsl(120, 100%, 40%);">+%  MGW 2</span><br><span style="color: hsl(120, 100%, 40%);">+%   mgcp-client:   connected</span><br><span style="color: hsl(120, 100%, 40%);">+%   service:       unblocked</span><br><span style="color: hsl(120, 100%, 40%);">+%   ongoing calls: 0</span><br><span style="color: hsl(120, 100%, 40%);">+----</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+It should be noted that MGCP a protocol is used via UDP, the connect only</span><br><span style="color: hsl(120, 100%, 40%);">+happens locally to forward the UDP datagrams properly. Also (unless a reset</span><br><span style="color: hsl(120, 100%, 40%);">+endpoint is configured like in the example config above) there will be no</span><br><span style="color: hsl(120, 100%, 40%);">+immediate interaction with the MGW. However, the log should at least confirm</span><br><span style="color: hsl(120, 100%, 40%);">+the the connect worked and the MGCP client has been created successfully.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+----</span><br><span style="color: hsl(120, 100%, 40%);">+Mon Aug  2 17:15:00 2021 DLMGCP mgcp_client.c:788 MGCP client: using endpoint domain '@mgw'</span><br><span style="color: hsl(120, 100%, 40%);">+Mon Aug  2 17:15:00 2021 DLMGCP mgcp_client.c:908 MGCP GW connection: r=127.0.0.1:2427<->l=127.0.0.1:2727</span><br><span style="color: hsl(120, 100%, 40%);">+----</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+It is strongly advised to check the activity on the related MGW and to follow</span><br><span style="color: hsl(120, 100%, 40%);">+the log in order to see that the communication between OsmoBSC and the MGW is</span><br><span style="color: hsl(120, 100%, 40%);">+working correctly.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+[[mgw_pooling_blocking]]</span><br><span style="color: hsl(120, 100%, 40%);">+==== Blocking an MGW / MGCP-Client</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+If it becomes apparent that an MGCP-Client must be restarted or removed from</span><br><span style="color: hsl(120, 100%, 40%);">+the config (maintenance) the operator can put that MGCP-Client into a blocked</span><br><span style="color: hsl(120, 100%, 40%);">+mode. A blocked MGCP-Client will still serve the ongoing calls but it will not</span><br><span style="color: hsl(120, 100%, 40%);">+be picked for the assignment of new calls.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+To block an MGCP-Client use the 'block' VTY command:</span><br><span style="color: hsl(120, 100%, 40%);">+----</span><br><span style="color: hsl(120, 100%, 40%);">+OsmoBSC# mgw 2 block</span><br><span style="color: hsl(120, 100%, 40%);">+OsmoBSC# show mgw-pool</span><br><span style="color: hsl(120, 100%, 40%);">+% MGW-Pool:</span><br><span style="color: hsl(120, 100%, 40%);">+%  MGW 0</span><br><span style="color: hsl(120, 100%, 40%);">+%   mgcp-client:   connected</span><br><span style="color: hsl(120, 100%, 40%);">+%   service:       unblocked</span><br><span style="color: hsl(120, 100%, 40%);">+%   ongoing calls: 11</span><br><span style="color: hsl(120, 100%, 40%);">+%  MGW 1</span><br><span style="color: hsl(120, 100%, 40%);">+%   mgcp-client:   connected</span><br><span style="color: hsl(120, 100%, 40%);">+%   service:       unblocked</span><br><span style="color: hsl(120, 100%, 40%);">+%   ongoing calls: 12</span><br><span style="color: hsl(120, 100%, 40%);">+%  MGW 2</span><br><span style="color: hsl(120, 100%, 40%);">+%   mgcp-client:   connected</span><br><span style="color: hsl(120, 100%, 40%);">+%   service:       blocked</span><br><span style="color: hsl(120, 100%, 40%);">+%   ongoing calls: 10</span><br><span style="color: hsl(120, 100%, 40%);">+----</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+When the number of ongoing calls has tapered off, the MGW / MGCP-Client can be</span><br><span style="color: hsl(120, 100%, 40%);">+restarted or removed if necessary.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+----</span><br><span style="color: hsl(120, 100%, 40%);">+OsmoBSC# show mgw-pool</span><br><span style="color: hsl(120, 100%, 40%);">+% MGW-Pool:</span><br><span style="color: hsl(120, 100%, 40%);">+%  MGW 0</span><br><span style="color: hsl(120, 100%, 40%);">+%   mgcp-client:   connected</span><br><span style="color: hsl(120, 100%, 40%);">+%   service:       unblocked</span><br><span style="color: hsl(120, 100%, 40%);">+%   ongoing calls: 15</span><br><span style="color: hsl(120, 100%, 40%);">+%  MGW 1</span><br><span style="color: hsl(120, 100%, 40%);">+%   mgcp-client:   connected</span><br><span style="color: hsl(120, 100%, 40%);">+%   service:       unblocked</span><br><span style="color: hsl(120, 100%, 40%);">+%   ongoing calls: 14</span><br><span style="color: hsl(120, 100%, 40%);">+%  MGW 2</span><br><span style="color: hsl(120, 100%, 40%);">+%   mgcp-client:   connected</span><br><span style="color: hsl(120, 100%, 40%);">+%   service:       blocked</span><br><span style="color: hsl(120, 100%, 40%);">+%   ongoing calls: 0</span><br><span style="color: hsl(120, 100%, 40%);">+----</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+If the blockade should be reverted, the 'unblock' VTY command can be used in</span><br><span style="color: hsl(120, 100%, 40%);">+the same way to remove the blockade. (Reconnecting will not remove the</span><br><span style="color: hsl(120, 100%, 40%);">+blockade.)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+==== Removing an MGW / MGCP-Client</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+An MGCP-Client is removed from the pool using the 'no mgw' command from the</span><br><span style="color: hsl(120, 100%, 40%);">+configure terminal. The MGCP-Client instance will automatically be terminated</span><br><span style="color: hsl(120, 100%, 40%);">+and the related resources are freed. The only requirement is that there are no</span><br><span style="color: hsl(120, 100%, 40%);">+ongoing calls on the selected instance.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+----</span><br><span style="color: hsl(120, 100%, 40%);">+OsmoBSC# configure terminal</span><br><span style="color: hsl(120, 100%, 40%);">+OsmoBSC(config)# network</span><br><span style="color: hsl(120, 100%, 40%);">+OsmoBSC(config-net)# no mgw 2</span><br><span style="color: hsl(120, 100%, 40%);">+----</span><br><span>diff --git a/doc/manuals/chapters/running.adoc b/doc/manuals/chapters/running.adoc</span><br><span>index 327e0bd..8e1c8e9 100644</span><br><span>--- a/doc/manuals/chapters/running.adoc</span><br><span>+++ b/doc/manuals/chapters/running.adoc</span><br><span>@@ -143,6 +143,9 @@</span><br><span> DLCX to the media gateway. This helps to clear lingering calls from the</span><br><span> media gateway when the OsmoBSC is restarted.</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+NOTE: OsmoBSC is also able to handle a pool of media gateways for load</span><br><span style="color: hsl(120, 100%, 40%);">+distribution. See also <<mgw_pooling>>.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> </span><br><span> ==== Configure Lb to connect to an SMLC</span><br><span> </span><br><span>diff --git a/doc/manuals/osmobsc-usermanual.adoc b/doc/manuals/osmobsc-usermanual.adoc</span><br><span>index c7589cc..120fe2c 100644</span><br><span>--- a/doc/manuals/osmobsc-usermanual.adoc</span><br><span>+++ b/doc/manuals/osmobsc-usermanual.adoc</span><br><span>@@ -32,6 +32,8 @@</span><br><span> </span><br><span> include::{srcdir}/chapters/mscpool.adoc[]</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+include::{srcdir}/chapters/mgwpool.adoc[]</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> include::{srcdir}/chapters/smlc.adoc[]</span><br><span> </span><br><span> include::./common/chapters/qos-dscp-pcp.adoc[]</span><br><span>diff --git a/include/osmocom/bsc/gsm_data.h b/include/osmocom/bsc/gsm_data.h</span><br><span>index db0f249..bed36f3 100644</span><br><span>--- a/include/osmocom/bsc/gsm_data.h</span><br><span>+++ b/include/osmocom/bsc/gsm_data.h</span><br><span>@@ -1203,8 +1203,15 @@</span><br><span>     struct osmo_timer_list bts_store_uptime_timer;</span><br><span> </span><br><span>   struct {</span><br><span style="color: hsl(120, 100%, 40%);">+              /* Single MGCP client configuration under msc node (also required for</span><br><span style="color: hsl(120, 100%, 40%);">+          * MGCP proxy when sccp-lite is used) */</span><br><span>             struct mgcp_client_conf *conf;</span><br><span style="color: hsl(0, 100%, 40%);">-          struct mgcp_client *client;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+         /* MGW pool, also includes the single MGCP client as fallback if no</span><br><span style="color: hsl(120, 100%, 40%);">+            * pool is configured. */</span><br><span style="color: hsl(120, 100%, 40%);">+             struct mgcp_client_pool *mgw_pool;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+          /* Timer definitions, the same for all MGW pool members */</span><br><span>           struct osmo_tdef *tdefs;</span><br><span>     } mgw;</span><br><span> </span><br><span>diff --git a/include/osmocom/bsc/vty.h b/include/osmocom/bsc/vty.h</span><br><span>index 9ea9835..70b973d 100644</span><br><span>--- a/include/osmocom/bsc/vty.h</span><br><span>+++ b/include/osmocom/bsc/vty.h</span><br><span>@@ -23,6 +23,7 @@</span><br><span> </span><br><span> enum bsc_vty_node {</span><br><span>   GSMNET_NODE = _LAST_OSMOVTY_NODE + 1,</span><br><span style="color: hsl(120, 100%, 40%);">+        MGW_NODE,</span><br><span>     BTS_NODE,</span><br><span>    TRX_NODE,</span><br><span>    TS_NODE,</span><br><span>diff --git a/src/osmo-bsc/bsc_subscr_conn_fsm.c b/src/osmo-bsc/bsc_subscr_conn_fsm.c</span><br><span>index afb633d..1e61d3f 100644</span><br><span>--- a/src/osmo-bsc/bsc_subscr_conn_fsm.c</span><br><span>+++ b/src/osmo-bsc/bsc_subscr_conn_fsm.c</span><br><span>@@ -45,6 +45,7 @@</span><br><span> #include <osmocom/bsc/assignment_fsm.h></span><br><span> #include <osmocom/bsc/codec_pref.h></span><br><span> #include <osmocom/mgcp_client/mgcp_client_endpoint_fsm.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/mgcp_client/mgcp_client_pool.h></span><br><span> #include <osmocom/core/byteswap.h></span><br><span> #include <osmocom/bsc/lb.h></span><br><span> #include <osmocom/bsc/lcs_loc_req.h></span><br><span>@@ -518,39 +519,47 @@</span><br><span>                                           uint16_t msc_assigned_cic, struct gsm_lchan *for_lchan)</span><br><span> {</span><br><span>         const char *epname;</span><br><span style="color: hsl(120, 100%, 40%);">+   struct mgcp_client *mgcp_client = NULL;</span><br><span> </span><br><span>  if (conn->user_plane.mgw_endpoint)</span><br><span>                return conn->user_plane.mgw_endpoint;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+  if (gscon_is_sccplite(conn) || gscon_is_aoip(conn)) {</span><br><span style="color: hsl(120, 100%, 40%);">+         /* Get MGCP client from pool */</span><br><span style="color: hsl(120, 100%, 40%);">+               mgcp_client = mgcp_client_pool_get(conn->network->mgw.mgw_pool);</span><br><span style="color: hsl(120, 100%, 40%);">+                if (!mgcp_client) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   LOGPFSML(conn->fi, LOGL_ERROR,</span><br><span style="color: hsl(120, 100%, 40%);">+                              "cannot ensure MGW endpoint -- no MGW configured, check configuration!\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                        conn->user_plane.mgw_endpoint = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+                      return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+          }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  if (gscon_is_sccplite(conn)) {</span><br><span>               /* derive endpoint name from CIC on A interface side */</span><br><span>              conn->user_plane.mgw_endpoint =</span><br><span>                   osmo_mgcpc_ep_alloc(conn->fi, GSCON_EV_FORGET_MGW_ENDPOINT,</span><br><span style="color: hsl(0, 100%, 40%);">-                                      conn->network->mgw.client,</span><br><span style="color: hsl(120, 100%, 40%);">+                                      mgcp_client,</span><br><span>                                         conn->network->mgw.tdefs,</span><br><span>                                      conn->fi->id,</span><br><span>                                          "%x@%s", msc_assigned_cic,</span><br><span style="color: hsl(0, 100%, 40%);">-                                            mgcp_client_endpoint_domain(conn->network->mgw.client));</span><br><span style="color: hsl(120, 100%, 40%);">+                                        mgcp_client_endpoint_domain(mgcp_client));</span><br><span>               LOGPFSML(conn->fi, LOGL_DEBUG, "MGW endpoint name derived from CIC 0x%x: %s\n",</span><br><span>                          msc_assigned_cic, osmo_mgcpc_ep_name(conn->user_plane.mgw_endpoint));</span><br><span> </span><br><span>        } else if (gscon_is_aoip(conn)) {</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span>            if (is_ipaccess_bts(for_lchan->ts->trx->bts))</span><br><span>                       /* use dynamic RTPBRIDGE endpoint allocation in MGW */</span><br><span style="color: hsl(0, 100%, 40%);">-                  epname = mgcp_client_rtpbridge_wildcard(conn->network->mgw.client);</span><br><span style="color: hsl(120, 100%, 40%);">+                     epname = mgcp_client_rtpbridge_wildcard(mgcp_client);</span><br><span>                else {</span><br><span style="color: hsl(0, 100%, 40%);">-                  epname = mgcp_client_e1_epname(conn, conn->network->mgw.client, for_lchan->ts->e1_link.e1_nr,</span><br><span style="color: hsl(120, 100%, 40%);">+                     epname = mgcp_client_e1_epname(conn, mgcp_client, for_lchan->ts->e1_link.e1_nr,</span><br><span>                                                       for_lchan->ts->e1_link.e1_ts, 16,</span><br><span>                                                      for_lchan->ts->e1_link.e1_ts_ss*2);</span><br><span>             }</span><br><span> </span><br><span>                conn->user_plane.mgw_endpoint =</span><br><span style="color: hsl(0, 100%, 40%);">-                      osmo_mgcpc_ep_alloc(conn->fi, GSCON_EV_FORGET_MGW_ENDPOINT,</span><br><span style="color: hsl(0, 100%, 40%);">-                                      conn->network->mgw.client,</span><br><span style="color: hsl(0, 100%, 40%);">-                                        conn->network->mgw.tdefs,</span><br><span style="color: hsl(0, 100%, 40%);">-                                         conn->fi->id,</span><br><span style="color: hsl(0, 100%, 40%);">-                                     "%s", epname);</span><br><span style="color: hsl(120, 100%, 40%);">+                  osmo_mgcpc_ep_alloc(conn->fi, GSCON_EV_FORGET_MGW_ENDPOINT, mgcp_client,</span><br><span style="color: hsl(120, 100%, 40%);">+                                       conn->network->mgw.tdefs, conn->fi->id, "%s", epname);</span><br><span>     } else {</span><br><span>             LOGPFSML(conn->fi, LOGL_ERROR, "Conn is neither SCCPlite nor AoIP!?\n");</span><br><span>                return NULL;</span><br><span>@@ -801,6 +810,12 @@</span><br><span> </span><br><span> static void gscon_forget_mgw_endpoint(struct gsm_subscriber_connection *conn)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct mgcp_client *mgcp_client;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* Put MGCP client back into MGW pool */</span><br><span style="color: hsl(120, 100%, 40%);">+      mgcp_client = osmo_mgcpc_ep_client(conn->user_plane.mgw_endpoint);</span><br><span style="color: hsl(120, 100%, 40%);">+ mgcp_client_pool_put(mgcp_client);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>         conn->user_plane.mgw_endpoint = NULL;</span><br><span>     conn->user_plane.mgw_endpoint_ci_msc = NULL;</span><br><span>      conn->ho.created_ci_for_msc = NULL;</span><br><span>diff --git a/src/osmo-bsc/bsc_vty.c b/src/osmo-bsc/bsc_vty.c</span><br><span>index 17fdb45..5ccd784 100644</span><br><span>--- a/src/osmo-bsc/bsc_vty.c</span><br><span>+++ b/src/osmo-bsc/bsc_vty.c</span><br><span>@@ -37,6 +37,7 @@</span><br><span> #include <osmocom/gsm/gsm0502.h></span><br><span> </span><br><span> #include <osmocom/mgcp_client/mgcp_client_endpoint_fsm.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/mgcp_client/mgcp_client_pool.h></span><br><span> </span><br><span> #include <osmocom/bsc/vty.h></span><br><span> #include <osmocom/bsc/gsm_data.h></span><br><span>@@ -3384,6 +3385,7 @@</span><br><span>       install_element(GSMNET_NODE, &cfg_net_nri_null_del_cmd);</span><br><span> </span><br><span>     bts_vty_init();</span><br><span style="color: hsl(120, 100%, 40%);">+        mgcp_client_pool_vty_init(GSMNET_NODE, MGW_NODE, " ", vty_global_gsm_network->mgw.mgw_pool);</span><br><span> </span><br><span>       install_element(ENABLE_NODE, &drop_bts_cmd);</span><br><span>     install_element(ENABLE_NODE, &restart_bts_cmd);</span><br><span>diff --git a/src/osmo-bsc/osmo_bsc_main.c b/src/osmo-bsc/osmo_bsc_main.c</span><br><span>index b3bd365..14cbc22 100644</span><br><span>--- a/src/osmo-bsc/osmo_bsc_main.c</span><br><span>+++ b/src/osmo-bsc/osmo_bsc_main.c</span><br><span>@@ -57,6 +57,7 @@</span><br><span> #include <osmocom/vty/cpu_sched_vty.h></span><br><span> </span><br><span> #include <osmocom/mgcp_client/mgcp_client_endpoint_fsm.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/mgcp_client/mgcp_client_pool.h></span><br><span> </span><br><span> #include <osmocom/abis/abis.h></span><br><span> #include <osmocom/bsc/abis_om2000.h></span><br><span>@@ -70,6 +71,7 @@</span><br><span> #include <osmocom/bsc/bsc_stats.h></span><br><span> </span><br><span> #include <osmocom/mgcp_client/mgcp_client.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/mgcp_client/mgcp_client_pool.h></span><br><span> </span><br><span> #include <osmocom/sigtran/xua_msg.h></span><br><span> </span><br><span>@@ -867,6 +869,41 @@</span><br><span> extern void *tall_tqe_ctx;</span><br><span> extern void *tall_ctr_ctx;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static int bsc_mgw_setup(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     struct mgcp_client *mgcp_client_single;</span><br><span style="color: hsl(120, 100%, 40%);">+       unsigned int pool_members_initalized;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       /* Initalize MGW pool. This initalizes and connects all MGCP clients that are currently configured in</span><br><span style="color: hsl(120, 100%, 40%);">+  * the pool. Adding additional MGCP clients to the pool is possible but the user has to configure and</span><br><span style="color: hsl(120, 100%, 40%);">+  * (re)connect them manually from the VTY. */</span><br><span style="color: hsl(120, 100%, 40%);">+ pool_members_initalized = mgcp_client_pool_connect(bsc_gsmnet->mgw.mgw_pool);</span><br><span style="color: hsl(120, 100%, 40%);">+      if (pool_members_initalized) {</span><br><span style="color: hsl(120, 100%, 40%);">+                LOGP(DNM, LOGL_NOTICE,</span><br><span style="color: hsl(120, 100%, 40%);">+                     "MGW pool with %u pool members configured, (ignoring MGW configuration in VTY node 'msc').\n",</span><br><span style="color: hsl(120, 100%, 40%);">+              pool_members_initalized);</span><br><span style="color: hsl(120, 100%, 40%);">+                return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Initialize and connect a single MGCP client. This MGCP client will appear as the one and only pool</span><br><span style="color: hsl(120, 100%, 40%);">+  * member if there is no MGW pool configured. */</span><br><span style="color: hsl(120, 100%, 40%);">+      LOGP(DNM, LOGL_NOTICE, "No MGW pool configured, using MGW configuration in VTY node 'msc'\n");</span><br><span style="color: hsl(120, 100%, 40%);">+        mgcp_client_single = mgcp_client_init(bsc_gsmnet, bsc_gsmnet->mgw.conf);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!mgcp_client_single) {</span><br><span style="color: hsl(120, 100%, 40%);">+            LOGP(DNM, LOGL_ERROR, "MGW (single) client initalization failed\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+     if (mgcp_client_connect(mgcp_client_single)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                LOGP(DNM, LOGL_ERROR, "MGW (single) connect failed at (%s:%u)\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                bsc_gsmnet->mgw.conf->remote_addr,</span><br><span style="color: hsl(120, 100%, 40%);">+              bsc_gsmnet->mgw.conf->remote_port);</span><br><span style="color: hsl(120, 100%, 40%);">+                return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+     mgcp_client_pool_register_single(bsc_gsmnet->mgw.mgw_pool, mgcp_client_single);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> int main(int argc, char **argv)</span><br><span> {</span><br><span>       struct bsc_msc_data *msc;</span><br><span>@@ -897,6 +934,7 @@</span><br><span>      }</span><br><span> </span><br><span>        bsc_gsmnet->mgw.conf = talloc_zero(bsc_gsmnet, struct mgcp_client_conf);</span><br><span style="color: hsl(120, 100%, 40%);">+   bsc_gsmnet->mgw.mgw_pool = mgcp_client_pool_alloc(bsc_gsmnet);</span><br><span>    mgcp_client_conf_init(bsc_gsmnet->mgw.conf);</span><br><span> </span><br><span>  bts_init();</span><br><span>@@ -1000,14 +1038,8 @@</span><br><span>                 }</span><br><span>    }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   bsc_gsmnet->mgw.client = mgcp_client_init(bsc_gsmnet, bsc_gsmnet->mgw.conf);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-      if (mgcp_client_connect(bsc_gsmnet->mgw.client)) {</span><br><span style="color: hsl(0, 100%, 40%);">-           LOGP(DNM, LOGL_ERROR, "MGW connect failed at (%s:%u)\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                   bsc_gsmnet->mgw.conf->remote_addr,</span><br><span style="color: hsl(0, 100%, 40%);">-                bsc_gsmnet->mgw.conf->remote_port);</span><br><span style="color: hsl(120, 100%, 40%);">+        if (bsc_mgw_setup() != 0)</span><br><span>            exit(1);</span><br><span style="color: hsl(0, 100%, 40%);">-        }</span><br><span> </span><br><span>        if (osmo_bsc_sigtran_init(&bsc_gsmnet->mscs) != 0) {</span><br><span>          LOGP(DNM, LOGL_ERROR, "Failed to initialize sigtran backhaul.\n");</span><br><span>diff --git a/tests/handover/handover_test.c b/tests/handover/handover_test.c</span><br><span>index f76a700..a355d3b 100644</span><br><span>--- a/tests/handover/handover_test.c</span><br><span>+++ b/tests/handover/handover_test.c</span><br><span>@@ -52,6 +52,7 @@</span><br><span> #include <osmocom/bsc/bts.h></span><br><span> #include <osmocom/bsc/paging.h></span><br><span> #include <osmocom/bsc/vty.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/mgcp_client/mgcp_client_pool.h></span><br><span> </span><br><span> #include "../../bscconfig.h"</span><br><span> </span><br><span>@@ -1617,6 +1618,12 @@</span><br><span>       if (!bsc_gsmnet)</span><br><span>             exit(1);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+  /* The MGCP client which is handling the pool (mgcp_client_pool_vty_init) is used from the bsc_vty_init, so</span><br><span style="color: hsl(120, 100%, 40%);">+    * we must allocate an empty mgw pool even though we do not need it for this test. */</span><br><span style="color: hsl(120, 100%, 40%);">+ bsc_gsmnet->mgw.mgw_pool = mgcp_client_pool_alloc(bsc_gsmnet);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!bsc_gsmnet->mgw.mgw_pool)</span><br><span style="color: hsl(120, 100%, 40%);">+             exit(1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>   vty_init(&vty_info);</span><br><span>     bsc_vty_init(bsc_gsmnet);</span><br><span>    ho_test_vty_init();</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-bsc/+/25123">change 25123</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/osmo-bsc/+/25123"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmo-bsc </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I8f33ab2cea04b545c403a6fe479aa963a0fc0d0d </div>
<div style="display:none"> Gerrit-Change-Number: 25123 </div>
<div style="display:none"> Gerrit-PatchSet: 14 </div>
<div style="display:none"> Gerrit-Owner: dexter <pmaier@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>
<div style="display:none"> Gerrit-Reviewer: daniel <dwillmann@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: dexter <pmaier@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-Reviewer: osmith <osmith@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>