Project

General

Profile

Bug #4319

determine auc_3g_ind from actual source_name of a request, not from the GSUP client conn

Added by neels almost 2 years ago. Updated over 1 year ago.

Status:
In Progress
Priority:
High
Assignee:
Target version:
-
Start date:
12/12/2019
Due date:
% Done:

90%

Spec Reference:

Description

Each VLR requesting auth tuples should use a distinct IND bucket for 3G auth.
Currently we do that by assigning a different IND to each connected client.
Since MSC and SGSN for a given subscriber are two distinct GSUP peers, they will end up using distinct INDs.

However, in a distributed setup, a roaming subscriber has one direct GSUP peer proxying for both remote MSC and SGSN.
That means as soon as a subscriber roams to a different site, the site's MSC and SGSN compete for the same IND bucket and waste SQNs rapidly.

So instead of using the local client as IND, we need to keep a list of VLR names and assign a different IND to each.
Then we use the GSUP source_name as indicator, which reflects the actual remote VLR's name.
Hence MSC and SGSN will be distinct INDs also for remote sites.

This could be done in-mem like now, but would also be better to persist in the database.

In #4305, there is a discussion about IND collisions across remote sites.
The discussion goes about how often per day a subscriber is likely to pass between sites that have identical INDs set.
When thinking about MSC vs SGSN INDs, however, an IND collision would be far worse, because each and every CS and PS Complete-Layer-3 would waste SQNs and load osmo-hlr to generate auth all the time.

So it would make sense to have a built-in scheme that definitely and always avoids CS vs. PS IND collisions.
We could simply assign even-numbered INDs to CS and odd INDs to PS.


Related issues

Related to OsmoMSC - Feature #4318: osmo-msc should indicate CS-domain in GSUP SendAuthInfo-RequestResolved12/12/2019

Associated revisions

Revision 5676fecc (diff)
Added by Neels Hofmeyr 3 months ago

db v6: determine 3G AUC IND from VLR name

Each VLR requesting auth tuples should use a distinct IND pool for 3G auth. So
far we tied the IND to the GSUP peer connection; MSC and SGSN were always
distinct GSUP peers, they ended up using distinct INDs.

However, we have implemented a GSUP proxy, so that, in a distributed setup, a
remotely roaming subscriber has only one direct GSUP peer proxying for both
remote MSC and SGSN. That means as soon as a subscriber roams to a different
site, we would use the GSUP proxy name to determine the IND instead of the
separate MSC and SGSN. The site's MSC and SGSN appear as the same client, get
the same IND bucket, waste SQNs rapidly and cause auth tuple generation load.

So instead of using the local client as IND, persistently keep a list of VLR
names and assign a different IND to each. Use the gsup_req->source_name as
indicator, which reflects the actual remote VLR's name (remote MSC or SGSN).

Persist the site <-> IND assignments in the database.

Add an IND test to db_test.c

There was an earlier patch version that separated the IND pools by cn_domain,
but it turned out to add complex semantics, while only solving one aspect of
the "adjacent VLR" problem. We need a solution not only for CS vs PS, but also
for 2,3G vs 4G, and for sites that are physically adjacent to each other. This
patch version does not offer any automatic solution for that -- as soon as more
than 2^IND_bitlen (usually 32) VLRs show up, it is the responsibility of the
admin to ensure the 'ind' table in the hlr.db does not have unfortunate IND
assignments. So far no VTY commands exist for that, they may be added in the
future.

Related: OS#4319
Change-Id: I6f0a6bbef3a27507605c3b4a0e1a89bdfd468374

Revision 9a0f24c2 (diff)
Added by Neels Hofmeyr 3 months ago

db v6: determine 3G AUC IND from VLR name

Each VLR requesting auth tuples should use a distinct IND pool for 3G
auth. So far we tied the IND to the GSUP peer connection; MSC and SGSN
were always distinct GSUP peers, they ended up using distinct INDs.

However, we have implemented a GSUP proxy, so that, in a distributed
setup, a remotely roaming subscriber has only one direct GSUP peer
proxying for both remote MSC and SGSN. That means as soon as a
subscriber roams to a different site, we would use the GSUP proxy name
to determine the IND instead of the separate MSC and SGSN. The site's
MSC and SGSN appear as the same client, get the same IND bucket, waste
SQNs rapidly and cause auth tuple generation load.

So instead of using the local client as IND, persistently keep a list of
VLR names and assign a different IND to each. Use the
gsup_req->source_name as indicator, which reflects the actual remote
VLR's name (remote MSC or SGSN).

Persist the site <-> IND assignments in the database.

Add an IND test to db_test.c

There was an earlier patch version that separated the IND pools by
cn_domain, but it turned out to add complex semantics, while only
solving one aspect of the "adjacent VLR" problem. We need a solution not
only for CS vs PS, but also for 2,3G vs 4G, and for sites that are
physically adjacent to each other. This patch version does not offer any
automatic solution for that -- as soon as more than 2^IND_bitlen
(usually 32) VLRs show up, it is the responsibility of the admin to
ensure the 'ind' table in the hlr.db does not have unfortunate IND
assignments. So far no VTY commands exist for that, they may be added in
the future.

Related: OS#4319
Change-Id: I6f0a6bbef3a27507605c3b4a0e1a89bdfd468374

Revision 3f9d1977 (diff)
Added by Neels Hofmeyr 3 months ago

db v6: determine 3G AUC IND from VLR name

Each VLR requesting auth tuples should use a distinct IND pool for 3G
auth. So far we tied the IND to the GSUP peer connection; MSC and SGSN
were always distinct GSUP peers, they ended up using distinct INDs.

However, we have implemented a GSUP proxy, so that, in a distributed
setup, a remotely roaming subscriber has only one direct GSUP peer
proxying for both remote MSC and SGSN. That means as soon as a
subscriber roams to a different site, we would use the GSUP proxy name
to determine the IND instead of the separate MSC and SGSN. The site's
MSC and SGSN appear as the same client, get the same IND bucket, waste
SQNs rapidly and cause auth tuple generation load.

So instead of using the local client as IND, persistently keep a list of
VLR names and assign a different IND to each. Use the
gsup_req->source_name as indicator, which reflects the actual remote
VLR's name (remote MSC or SGSN).

Persist the site <-> IND assignments in the database.

Add an IND test to db_test.c

There was an earlier patch version that separated the IND pools by
cn_domain, but it turned out to add complex semantics, while only
solving one aspect of the "adjacent VLR" problem. We need a solution not
only for CS vs PS, but also for 2,3G vs 4G, and for sites that are
physically adjacent to each other. This patch version does not offer any
automatic solution for that -- as soon as more than 2^IND_bitlen
(usually 32) VLRs show up, it is the responsibility of the admin to
ensure the 'ind' table in the hlr.db does not have unfortunate IND
assignments. So far no VTY commands exist for that, they may be added in
the future.

Related: OS#4319
Change-Id: I6f0a6bbef3a27507605c3b4a0e1a89bdfd468374

History

#1 Updated by neels almost 2 years ago

  • Assignee set to neels
  • Priority changed from Normal to High

#2 Updated by neels almost 2 years ago

  • Description updated (diff)

#3 Updated by neels almost 2 years ago

  • Related to Feature #4318: osmo-msc should indicate CS-domain in GSUP SendAuthInfo-Request added

#4 Updated by neels almost 2 years ago

  • Description updated (diff)
  • Status changed from New to In Progress

#5 Updated by neels almost 2 years ago

  • % Done changed from 0 to 50

#6 Updated by neels almost 2 years ago

neels wrote:

So it would make sense to have a built-in scheme that definitely and always avoids CS vs. PS IND collisions.
We could simply assign even-numbered INDs to CS and odd INDs to PS.

This part is not as trivial as I thought at first. It is of course easy to make sure that a CS IND is always even and a PS IND is always odd, but what also plays into this is that the source_name also differs for MSC vs. SGSN.

Example: site A has 'MSC-A' and 'SGSN-A'.
My first idea would be to keep one table of known source_name entities, and apply the CS/PS bit after that.
This plays out as:

idx source_name resulting IND
1 'MSC-A' (1 << 1) = 2
2 'SGSN-A' (2 << 1) + 1 = 5

I get 2 and 5, where I would have liked to get 0 and 1.
It is not actually a problem that it starts with 2, so I am fine with geting 2 and 3.
But since SGSN-A has table index 2, I get 2 and 5.
Imagine every site always showing up with MSC and SGSN in sequence, then we would have

idx source_name resulting IND ((idx << 1) + ps ) % 32
1 MSC-A 2
2 SGSN-A 5
3 MSC-B 6
4 SGSN-B 9
5 MSC-C 10
6 SGSN-C 13
7 MSC-D 14
8 SGSN-D 17
9 MSC-E 18
10 SGSN-E 21
11 MSC-F 22
12 SGSN-F 25
13 MSC-G 26
14 SGSN-G 29
15 MSC-H 30
16 SGSN-H 1
17 MSC-I 2
18 SGSN-I 5

i.e. the cumulative effect of SGSN getting only every other table index + the separation makes us use only half the IND space by skipping every other IND, and actually upon IND number space wrapping, makes us wrap exactly back to the already used IND instead of those in-between: we use 2 and 6 for MSC, but never 0 or 4.

I would still like to separate CS and PS INDs for certain, though, yet not rely on the MSCs and SGSNs to always turn up nicely in sequence.
So I need separate tables for CS and PS.

1 MSC-A 2
2 MSC-B 4
3 MSC-C 6
4 MSC-D 8
5 MSC-E 10
6 MSC-F 12
7 MSC-G 14
8 MSC-H 16
9 MSC-I 18
10 MSC-J 20
11 MSC-K 22
12 MSC-L 24
13 MSC-M 26
14 MSC-N 28
15 MSC-O 30
16 MSC-P 0
1 SGSN-A 3
2 SGSN-B 5
3 SGSN-C 7
4 SGSN-D 9
5 SGSN-E 11
6 SGSN-F 13
7 SGSN-G 15
8 SGSN-H 17
9 SGSN-I 19
10 SGSN-J 21
11 SGSN-K 23
12 SGSN-L 25
13 SGSN-M 27
14 SGSN-N 29
15 SGSN-O 31
16 SGSN-P 1
17 SGSN-Q 3

(Separate tables allow using SQLite PRIMARY KEY autoincrement independently.)

#7 Updated by neels almost 2 years ago

found a way to have both in one table with disctinct indexes for each cn_domain,
with the benefit that the cn_domain is just a number, and arbitrary other cn_domains could be invented without needing to change the db scheme.

((We could use a separate cn_domain (OSMO_GSUP_CN_DOMAIN_NONE == 0) for those SendAuthInfo requests that failed to send a CN domain at all.
The benefit would be nil though -- I'm not going to <<1 another bit to assign actually half of all IND space for omitted CN domain indicators. Ok, nice feat but not useful unless we actually have more valid CN domains.))

CREATE TABLE ind (
       cn_domain INTEGER NOT NULL,
       -- 3G auth IND bucket to be used for this VLR, where IND = (idx << 1) + is_ps
       ind     INTEGER NOT NULL,
       -- VLR identification, usually the GSUP source_name
       vlr     TEXT NOT NULL,
       PRIMARY KEY(ind),
       UNIQUE (cn_domain, vlr)
);
insert into ind (cn_domain, ind, vlr) select $cn_domain, count(ind)*2+$cn_domain-1, $vlr from ind where cn_domain = $cn_domain;

#8 Updated by neels almost 2 years ago

meh, that looks nice because it directly shows the actually used IND, but leads to problems adding new entries as soon as one of them is removed from the middle. Separate tables may be necessary after all, unless I find something nifty to also cover that.

Another aspect is that we might like an IND to become re-used if it was deleted, instead of first wrapping around the entire number space.
So unless some SQL magic shows up that converges in finite time, we'll actually need to read all IND entries into RAM and handle all those constraints in C instead.

#9 Updated by neels almost 2 years ago

  • % Done changed from 50 to 80

This does exactly what we want:


CREATE TABLE ind (
        cn_domain INTEGER NOT NULL,
        -- 3G auth IND bucket to be used for this VLR, where IND = (idx << 1) + cn_domain -1
        ind     INTEGER PRIMARY KEY,
        -- VLR identification, usually the GSUP source_name
        vlr     TEXT NOT NULL,
        UNIQUE (cn_domain, vlr)
);

insert into ind (cn_domain, ind, vlr)
SELECT  $cn_domain,
        CASE WHEN EXISTS(SELECT NULL from ind where cn_domain = $cn_domain LIMIT 1)
        THEN
                (
                SELECT ((ind + 2) - ((ind + 2)%2) + ($cn_domain-1))
                FROM    ind as mo WHERE   NOT EXISTS (SELECT NULL FROM ind as mi
                WHERE cn_domain = $cn_domain and mi.ind = ((mo.ind + 2) - ((mo.ind + 2)%2) + $cn_domain-1)) ORDER BY ind LIMIT 1
                )
        ELSE ($cn_domain-1)
        END ind
        , $vlr;

#10 Updated by neels almost 2 years ago

Patch is implemented and passes C tests. Next up is test in a live environment and verify that ttcn3 suite still passes.

#11 Updated by neels almost 2 years ago

Turns out that bit-shifting separation isn't such a great idea after all.
See https://osmocom.org/issues/4318#note-7

We do need some way or other of getting adjacent sites into distinct IND pools,
all of:
- CS and PS of the same site
- 4G and 23G of the same site
- physically adjacent separate sites.
By now I think my bit shifting idea is not a good one at all, because it
addresses only one of the above points. We need a solution for all of them.

Instead, I will roll back that complexity and use a simple incrementing IND across all VLR names.

#12 Updated by neels over 1 year ago

  • % Done changed from 80 to 90

#13 Updated by neels over 1 year ago

  • Status changed from In Progress to Resolved
  • % Done changed from 90 to 100

merged

#14 Updated by neels over 1 year ago

  • Status changed from Resolved to In Progress
  • % Done changed from 100 to 90

whoops sorry, this one is still waiting on gerrit

Also available in: Atom PDF

Add picture from clipboard (Maximum size: 48.8 MB)