== SGSN Pooling

SGSN pooling is described in 3GPP TS 23.236 <<3gpp-ts-23-236>>, and is supported
by OsmoGbProxy since early 2021.

The aim of SGSN pooling is to distribute load from a BSS across multiple SGSNs,
which are equivalent and redundant infrastructure for the same core network.

The main mechanism for SGSN pooling is the TLLI/P-TMSI, which an SGSN hands out
to its attached subscribers. Typically 10 bits of the P-TMSI are designated as a
Network Resource Identifier (NRI) that identifies the originating SGSN, and
allows OsmoGbProxy to direct a subscriber back to the same SGSN instance that
previously negotiated the Attach procedure. Typically, the full NRI value
range available is divided into N even ranges, where each SGSN is assigned one
NRI range.

Subscribers attaching without a TLLI, or those with unknown NRI value,
are evenly distributed across SGSN instances. OsmoGbProxy uses a hash-based
approach to distribute load across all connected SGSNs.

A Paging Response from a subscriber is always returned back to whichever SGSN
initiated the Paging, regardless of the Mobile Identity used.

Finally, a NULL-NRI is a special NRI value that indicates that the SGSN wishes
to offload this subscriber to a different SGSN. A NULL-NRI is an arbitrary NRI
value that is chosen distinctly for each PLMN served by a BSS, so that a
subscriber can be reassigned within that PLMN. Upon (periodic) Location
Updating, an offloading SGSN hands out a NULL-NRI value in the assigned TLLI,
along with a non-broadcast LAI. The subscriber will notice the LAI mismatch,
and immediately re-attempt the attach using the TLLI containing the NULL-NRI.
OsmoGbProxy recognises the NULL-NRI and redirects the subscriber to one of the
other SGSNs. A prerequisite for this to work well is that the particular SGSN is
previously marked as not accepting new subscribers, in OsmoGbProxy's configuration.

The mechanisms described above make up the NAS node selection function
implemented in OsmoGbProxy.

3GPP TS 23.236 also defines that an offloading SGSN hands subscriber information
to the newly assigned SGSN, which takes place outside the scope of OsmoGbProxy.

=== Configuring SGSN Pooling

The NRI ranges assigned to each SGSN must match in the OsmoGbProxy and the SGSN
configuration. If inconsistent NRI value ranges are configured,
attached subscribers would be redirected to SGSN instances that did not perform the
attach, possibly rendering the core network unusable.

==== Connecting Multiple SGSNs

----
! Configure the Network Service
ns
 bind udp sgsn
  listen 10.0.0.1 23000
 nse 1
  ip-sns-bind sgsn
  ip-sns-remote 10.0.1.1 23000
  ip-sns-remote 10.0.1.1 23001
 nse 2
  ip-sns-bind sgsn
  ip-sns-remote 10.0.1.2 23000
 nse 3
  ip-sns-bind sgsn
  ip-sns-remote 10.0.1.3 23000
! configure NRI value ranges
gbproxy
 nri bitlen 10
 nri null add 0
sgsn nsei 1
 name SGSN01
 nri add 1 341
sgsn nsei 2
 name SGSN02
 nri add 342 682
sgsn nsei 3
 name SGSN03
 nri add 683 1023
----

==== NRI Value Bit Length

In OsmGbProxy, the NRI value's bit length is freely configurable from 0 to 15
bits. 3GPP TS 23.236 suggests a typical bit length of 10. Setting the length
to 0 disables SGSN pooling, this is also the default.
The NRI bit length must be identical across the entire SGSN pool.

Change the NRI value bit length in OsmoGbProxy's VTY configuration like this:

----
gbproxy
 nri bitlen 10
----

In the TMSI bits, regardless of the NRI bit length, the NRI value always starts
just after the most significant octet of a TMSI (most significant bit at TMSI's
bit 23).

==== NULL-NRI

Since OsmoGbProxy supports serving only one PLMN, NULL-NRI are configured globally.
Even though 3GPP TS 23.236 indicates that there is a single NULL-NRI per PLMN,
OsmoGbProxy allows configuring multiple NULL-NRI values.

----
network
 nri null add 0
 nri null add 423
----

==== Assigning NRI Ranges to SGSNs

Each SGSN configured in OsmoGbProxy must be assigned a distinct NRI value range.
Overlapping NRI value ranges will cause failure to serve subscribers.

NRI values are typically configured in ranges, here dividing a 10bit range
(0..1023) into three equal ranges, while leaving 0 available to be configured
as NULL-NRI:

----
sgsn nsei 1
 nri add 1 341
sgsn nsei 2
 nri add 342 684
sgsn nsei 3
 nri add 685 1023
----

NRI can also be assigned in single values:

----
sgsn nsei 1
 nri add 23
----

Ranges can be constructed arbitrarily by a sequence of `add` and `del`
configurations, here a contrived example:

----
sgsn nsei 1
 nri add 0 342
 nri del 23
 nri del 42 235
 nri add 1000 1023
----

On the VIEW and ENABLE VTY nodes, `show nri all` shows all SGSNs:

----
OsmoGbProxy> show nri all
sgsn nsei 1
 nri add 1 341
sgsn nsei 2
 nri add 342 684
sgsn nsei 3
 nri add 685 1023
----

When configuring overlapping NRI value ranges across SGSNs, the telnet VTY warns
about it, and starting OsmoGbProxy with such a configuration will fail:

----
sgsn nsei 1
 nri add 1 511
sgsn nsei 2
 nri add 512 1023
sgsn nsei 3
 nri add 500 555
----

This results in:

----
$ osmo-gbproxy
% Warning: NSE(00003/SGSN): NRI range [500..555] overlaps between NSE 00003 and NSE 00001. For overlaps, NSE 00001 has higher priority than NSE 00003
% Warning: NSE(00003/SGSN): NRI range [500..555] overlaps between NSE 00003 and NSE 00002. For overlaps, NSE 00002 has higher priority than NSE 00003
----

==== SGSN Offloading

To effectively offload a particular SGSN, it must be marked as no longer taking
new subscribers in OsmoGbProxy. This can be achieved in the telnet VTY by:

----
sgsn nsei 1
 no allow-attach
----

This SGSN will, as long as it is connected, continue to serve subscribers
already attached to it: those that yield an NRI matching this SGSN, and those
that are being paged by this SGSN. But OsmoGbProxy will no longer direct new
subscribers to this SGSN.

To re-enable an SGSN for attaching new subscribers:

----
sgsn nsei 1
 allow-attach
----

==== Traffic allocation

In a SGSN pool, osmo-gbproxy is facing the problem of dividing the downlink
capacity of a cell towards the SGSN.  The BSS advertises the per-BVC capacity
by means of the BSSGP FLOW-CONTROL-BVC messages, but as there are multiple
SGSN in a pool, they all have to share / divide that total capacity.

By default, osmo-gbproxy advertises the full capacity to _each_ of the SGSN
pool members, which results in significant over-provisioning and can lead to
overload situations.

The administrator can configure the _percentage_ of the overall BSS-advertised
capacity that shall be reported to each pool member SGSN using the
`pool bvc-flow-control-ratio <1-100>` configuration command.

A setting of 100 means that each pool member is informed of 100% of the
BSS side capacity.

A setting of 25 means that each pool member is informed of 25% of the
BSS side capacity.  This would make most sense in a set-up with four
SGSN of equal share.

More complex capacity division schemes are so far not supported by
osmo-gbproxy.
