blob: 1e73a1d6abdeec65a405edb2d74a9f4dfa129b2b [file] [log] [blame]
Daniel Willmann04075ec2021-03-10 09:48:18 +01001#pragma once
Neels Hofmeyr4b4c5862017-09-04 15:13:25 +02002
3#include <osmocom/core/msgb.h>
Alexander Couzens951e1332020-09-22 13:21:46 +02004#include <osmocom/core/timer.h>
Harald Weltee5209642020-12-05 19:59:45 +01005#include <osmocom/core/fsm.h>
Harald Welted2fef952020-12-05 00:31:07 +01006#include <osmocom/core/hashtable.h>
Neels Hofmeyr6179f0c2018-02-21 00:39:36 +01007#include <osmocom/gsm/gsm23003.h>
Daniel Willmannee834af2020-12-14 16:22:39 +01008#include <osmocom/gsm/gsm23236.h>
Philipp Maierda3af942021-02-04 21:54:09 +01009#include <osmocom/gsm/gsm48.h>
Daniel Willmannc8a50092021-01-17 13:11:41 +010010#include <osmocom/gsm/protocol/gsm_23_003.h>
Neels Hofmeyr4b4c5862017-09-04 15:13:25 +020011
Daniel Willmanna8b61652021-02-12 05:05:14 +010012#include <osmocom/gprs/frame_relay.h>
Alexander Couzens951e1332020-09-22 13:21:46 +020013#include <osmocom/gprs/gprs_ns2.h>
Neels Hofmeyr4b4c5862017-09-04 15:13:25 +020014#include <osmocom/vty/command.h>
15
16#include <sys/types.h>
17#include <regex.h>
Harald Weltebec70412019-03-22 09:44:42 +010018#include <stdbool.h>
Neels Hofmeyr4b4c5862017-09-04 15:13:25 +020019
20#define GBPROXY_INIT_VU_GEN_TX 256
Daniel Willmannee834af2020-12-14 16:22:39 +010021#define GBPROXY_MAX_NR_SGSN 16
Neels Hofmeyr4b4c5862017-09-04 15:13:25 +020022
Daniel Willmanna8b61652021-02-12 05:05:14 +010023/* Set conservative default BSSGP SDU (FR SDU - size of NS UNITDATA IEs) */
24#define DEFAULT_NSE_SDU (FRAME_RELAY_SDU - 4)
25
Daniel Willmann8f407b12020-12-02 19:33:50 +010026/* BVCI uses 16 bits */
27#define BVC_LOG_CTX_FLAG (1<<17)
28
Neels Hofmeyr4b4c5862017-09-04 15:13:25 +020029struct rate_ctr_group;
30struct gprs_gb_parse_context;
31struct tlv_parsed;
32
33enum gbproxy_global_ctr {
34 GBPROX_GLOB_CTR_INV_BVCI,
35 GBPROX_GLOB_CTR_INV_LAI,
36 GBPROX_GLOB_CTR_INV_RAI,
37 GBPROX_GLOB_CTR_INV_NSEI,
38 GBPROX_GLOB_CTR_PROTO_ERR_BSS,
39 GBPROX_GLOB_CTR_PROTO_ERR_SGSN,
40 GBPROX_GLOB_CTR_NOT_SUPPORTED_BSS,
41 GBPROX_GLOB_CTR_NOT_SUPPORTED_SGSN,
42 GBPROX_GLOB_CTR_RESTART_RESET_SGSN,
43 GBPROX_GLOB_CTR_TX_ERR_SGSN,
44 GBPROX_GLOB_CTR_OTHER_ERR,
Neels Hofmeyr4b4c5862017-09-04 15:13:25 +020045};
46
Harald Welte560bdb32020-12-04 22:24:47 +010047enum gbproxy_bvc_ctr {
Neels Hofmeyr4b4c5862017-09-04 15:13:25 +020048 GBPROX_PEER_CTR_BLOCKED,
49 GBPROX_PEER_CTR_UNBLOCKED,
50 GBPROX_PEER_CTR_DROPPED,
51 GBPROX_PEER_CTR_INV_NSEI,
52 GBPROX_PEER_CTR_TX_ERR,
Neels Hofmeyr4b4c5862017-09-04 15:13:25 +020053 GBPROX_PEER_CTR_LAST,
54};
55
Harald Welte4a8769a2019-03-22 08:26:45 +010056/* global gb-proxy configuration */
Neels Hofmeyr4b4c5862017-09-04 15:13:25 +020057struct gbproxy_config {
Harald Welte4a8769a2019-03-22 08:26:45 +010058 /* NS instance of libosmogb */
Alexander Couzens951e1332020-09-22 13:21:46 +020059 struct gprs_ns2_inst *nsi;
Neels Hofmeyr4b4c5862017-09-04 15:13:25 +020060
Harald Welte209dc9f2020-12-12 19:02:16 +010061 struct {
62 /* percentage of BVC flow control advertised to each SGSN in the pool */
63 uint8_t bvc_fc_ratio;
Daniel Willmannee834af2020-12-14 16:22:39 +010064 /* NRI bitlen and usable NULL-NRI ranges */
65 uint8_t nri_bitlen;
66 struct osmo_nri_ranges *null_nri_ranges;
Daniel Willmannb387c1e2020-12-27 18:14:39 +010067
68 /* Used for testing: If not NULL then this SGSN is returned by
69 * gbproxy_sgsn_by_tlli() */
70 struct gbproxy_sgsn *nsf_override;
Harald Welte209dc9f2020-12-12 19:02:16 +010071 } pool;
72
Daniel Willmannee834af2020-12-14 16:22:39 +010073 /* hash table of all BSS side Gb peers */
Harald Welted2fef952020-12-05 00:31:07 +010074 DECLARE_HASHTABLE(bss_nses, 8);
Neels Hofmeyr4b4c5862017-09-04 15:13:25 +020075
Harald Weltee5209642020-12-05 19:59:45 +010076 /* hash table of all SGSN-side Gb peers */
77 DECLARE_HASHTABLE(sgsn_nses, 8);
78
79 /* hash table of all gbproxy_cell */
80 DECLARE_HASHTABLE(cells, 8);
81
Daniel Willmann77493b12020-12-29 21:13:31 +010082 /* tlli<->nse cache used to map SUSPEND/RESUME (N)ACKS */
83 struct {
84 DECLARE_HASHTABLE(entries, 10);
85 struct osmo_timer_list timer;
86 /* Time in seconds that the entries should be valid */
87 uint8_t timeout;
88 } tlli_cache;
89
Daniel Willmannc8a50092021-01-17 13:11:41 +010090 /* imsi<->nse cache used for PAGING REJECT */
91 struct {
92 DECLARE_HASHTABLE(entries, 10);
93 struct osmo_timer_list timer;
94 /* Time in seconds that the entries should be valid */
95 uint8_t timeout;
96 } imsi_cache;
97
Daniel Willmannee834af2020-12-14 16:22:39 +010098 /* List of all SGSNs */
99 struct llist_head sgsns;
100
Neels Hofmeyr4b4c5862017-09-04 15:13:25 +0200101 /* Counter */
102 struct rate_ctr_group *ctrg;
Neels Hofmeyr4b4c5862017-09-04 15:13:25 +0200103};
104
Harald Weltee5209642020-12-05 19:59:45 +0100105/* One Cell within the BSS: Links BSS-side BVC to SGSN-side BVCs */
106struct gbproxy_cell {
107 /* linked to gbproxy_config.cells hashtable */
108 struct hlist_node list;
109
110 /* point back to the config */
111 struct gbproxy_config *cfg;
112
113 /* BVCI of PTP BVCs associated to this cell */
114 uint16_t bvci;
115
Philipp Maierda3af942021-02-04 21:54:09 +0100116 struct {
117 /* Routing Area that this cell is part of */
118 struct gprs_ra_id raid;
119
120 /* Cell ID of this cell */
121 uint16_t cid;
122 } id;
Harald Weltee5209642020-12-05 19:59:45 +0100123
124 /* pointer to the BSS-side BVC */
125 struct gbproxy_bvc *bss_bvc;
126
127 /* pointers to SGSN-side BVC (one for each pool member) */
Daniel Willmannee834af2020-12-14 16:22:39 +0100128 struct gbproxy_bvc *sgsn_bvc[GBPROXY_MAX_NR_SGSN];
Harald Weltee5209642020-12-05 19:59:45 +0100129};
130
Daniel Willmanne50550e2020-11-26 18:19:21 +0100131/* One BVC inside an NSE */
Harald Welte560bdb32020-12-04 22:24:47 +0100132struct gbproxy_bvc {
133 /* linked to gbproxy_nse.bvcs */
Harald Welte8b4c7942020-12-05 10:14:49 +0100134 struct hlist_node list;
Neels Hofmeyr4b4c5862017-09-04 15:13:25 +0200135
Harald Welte560bdb32020-12-04 22:24:47 +0100136 /* The NSE this BVC belongs to */
Daniel Willmanne50550e2020-11-26 18:19:21 +0100137 struct gbproxy_nse *nse;
Neels Hofmeyr4b4c5862017-09-04 15:13:25 +0200138
Harald Welte560bdb32020-12-04 22:24:47 +0100139 /* PTP BVCI of this BVC */
Neels Hofmeyr4b4c5862017-09-04 15:13:25 +0200140 uint16_t bvci;
Neels Hofmeyr4b4c5862017-09-04 15:13:25 +0200141
Philipp Maierda3af942021-02-04 21:54:09 +0100142 /* Routing Area that this BVC is part of */
143 struct gprs_ra_id raid;
Neels Hofmeyr4b4c5862017-09-04 15:13:25 +0200144
145 /* Counter */
146 struct rate_ctr_group *ctrg;
Harald Weltee5209642020-12-05 19:59:45 +0100147
148 /* the cell to which this BVC belongs */
149 struct gbproxy_cell *cell;
150
151 /* per-BVC FSM instance */
152 struct osmo_fsm_inst *fi;
Neels Hofmeyr4b4c5862017-09-04 15:13:25 +0200153};
154
Harald Welte560bdb32020-12-04 22:24:47 +0100155/* one NS Entity that we interact with (BSS/PCU) */
Daniel Willmanne50550e2020-11-26 18:19:21 +0100156struct gbproxy_nse {
Harald Welte2b7b1bb2020-12-04 23:58:20 +0100157 /* linked to gbproxy_config.bss_nses */
Harald Welted2fef952020-12-05 00:31:07 +0100158 struct hlist_node list;
Daniel Willmanne50550e2020-11-26 18:19:21 +0100159
160 /* point back to the config */
161 struct gbproxy_config *cfg;
162
Harald Welte560bdb32020-12-04 22:24:47 +0100163 /* NSEI of the NSE */
Daniel Willmanne50550e2020-11-26 18:19:21 +0100164 uint16_t nsei;
165
Daniel Willmann429c43c2021-03-10 09:44:34 +0100166 /* Maximum size of the NS-UNITDATA NS SDU that can be transported by the NSE */
Daniel Willmanna8b61652021-02-12 05:05:14 +0100167 uint16_t max_sdu_len;
168
Harald Weltee5209642020-12-05 19:59:45 +0100169 /* Are we facing towards a SGSN (true) or BSS (false) */
170 bool sgsn_facing;
Daniel Willmann37518b32021-05-27 18:13:36 +0200171 bool alive;
Harald Weltee5209642020-12-05 19:59:45 +0100172
Daniel Willmanne50550e2020-11-26 18:19:21 +0100173 /* List of all BVCs in this NSE */
Harald Welte8b4c7942020-12-05 10:14:49 +0100174 DECLARE_HASHTABLE(bvcs, 10);
Daniel Willmanne50550e2020-11-26 18:19:21 +0100175};
176
Daniel Willmannee834af2020-12-14 16:22:39 +0100177/* SGSN configuration such as pool options (only for NSE where sgsn_facing == true) */
178struct gbproxy_sgsn {
179 /* linked to gbproxy_config.sgsns */
180 struct llist_head list;
181
182 /* The NSE belonging to this SGSN */
183 struct gbproxy_nse *nse;
184
Daniel Willmanna648f3c2020-12-28 18:07:27 +0100185 /* Name of the SGSN */
186 char *name;
187
Daniel Willmannee834af2020-12-14 16:22:39 +0100188 /* Pool configuration for the sgsn (only valid if sgsn_facing == true) */
189 struct {
190 bool allow_attach;
191 struct osmo_nri_ranges *nri_ranges;
192 } pool;
193};
194
Daniel Willmann361d0b52021-07-09 17:44:30 +0200195enum cache_usage_type {
196 CACHE_USAGE_PAGING,
Daniel Willmannf024eeb2021-07-06 14:02:41 +0200197 CACHE_USAGE_MS_REG_ENQ,
Daniel Willmann361d0b52021-07-09 17:44:30 +0200198};
199
Daniel Willmann77493b12020-12-29 21:13:31 +0100200/* TLLI cache */
201struct gbproxy_tlli_cache_entry {
Daniel Willmannc8a50092021-01-17 13:11:41 +0100202 /* linked to gbproxy_config.tlli_cache.entries */
Daniel Willmann77493b12020-12-29 21:13:31 +0100203 struct hlist_node list;
204
205 /* TLLI of the entry */
206 uint32_t tlli;
Daniel Willmann361d0b52021-07-09 17:44:30 +0200207 enum cache_usage_type usage;
208
Daniel Willmann77493b12020-12-29 21:13:31 +0100209 /* When was this entry last seen */
210 time_t tstamp;
211 /* The Cell this TLLI was last seen */
212 struct gbproxy_nse *nse;
213};
214
Daniel Willmannc8a50092021-01-17 13:11:41 +0100215/* IMSI cache */
216struct gbproxy_imsi_cache_entry {
217 /* linked to gbproxy_config.imsi_cache.entries */
218 struct hlist_node list;
219
220 /* IMSI of the entry */
221 char imsi[OSMO_IMSI_BUF_SIZE];
Daniel Willmann361d0b52021-07-09 17:44:30 +0200222 enum cache_usage_type usage;
223
Daniel Willmannc8a50092021-01-17 13:11:41 +0100224 /* When was this entry last seen */
225 time_t tstamp;
226 /* The SGSN where the request came from */
227 struct gbproxy_nse *nse;
228};
229
Daniel Willmann066c4cb2020-12-01 16:36:29 +0100230/* Convenience logging macros for NSE/BVC */
231#define LOGPNSE_CAT(NSE, SUBSYS, LEVEL, FMT, ARGS...) \
Harald Weltee5209642020-12-05 19:59:45 +0100232 LOGP(SUBSYS, LEVEL, "NSE(%05u/%s) " FMT, (NSE)->nsei, \
233 (NSE)->sgsn_facing ? "SGSN" : "BSS", ## ARGS)
Daniel Willmann066c4cb2020-12-01 16:36:29 +0100234#define LOGPNSE(NSE, LEVEL, FMT, ARGS...) \
235 LOGPNSE_CAT(NSE, DGPRS, LEVEL, FMT, ## ARGS)
236
237#define LOGPBVC_CAT(BVC, SUBSYS, LEVEL, FMT, ARGS...) \
Harald Weltee5209642020-12-05 19:59:45 +0100238 LOGP(SUBSYS, LEVEL, "NSE(%05u/%s)-BVC(%05u/%s) " FMT, (BVC)->nse->nsei, \
239 (BVC)->nse->sgsn_facing ? "SGSN" : "BSS", (BVC)->bvci, \
240 osmo_fsm_inst_state_name((BVC)->fi), ## ARGS)
Daniel Willmann066c4cb2020-12-01 16:36:29 +0100241#define LOGPBVC(BVC, LEVEL, FMT, ARGS...) \
242 LOGPBVC_CAT(BVC, DGPRS, LEVEL, FMT, ## ARGS)
Neels Hofmeyr4b4c5862017-09-04 15:13:25 +0200243
Harald Weltecfc7e8e2020-12-07 12:03:10 +0100244#define LOGPCELL_CAT(CELL, SUBSYS, LEVEL, FMT, ARGS...) \
245 LOGP(SUBSYS, LEVEL, "CELL(%05u) " FMT, (CELL)->bvci, ## ARGS)
246#define LOGPCELL(CELL, LEVEL, FMT, ARGS...) \
247 LOGPCELL_CAT(CELL, DGPRS, LEVEL, FMT, ## ARGS)
248
Daniel Willmannee834af2020-12-14 16:22:39 +0100249#define LOGPSGSN_CAT(SGSN, SUBSYS, LEVEL, FMT, ARGS...) \
Daniel Willmanna648f3c2020-12-28 18:07:27 +0100250 LOGP(SUBSYS, LEVEL, "NSE(%05u)-SGSN(%s) " FMT, (SGSN)->nse->nsei, (SGSN)->name, ## ARGS)
Daniel Willmannee834af2020-12-14 16:22:39 +0100251#define LOGPSGSN(SGSN, LEVEL, FMT, ARGS...) \
252 LOGPSGSN_CAT(SGSN, DGPRS, LEVEL, FMT, ## ARGS)
253
Neels Hofmeyr4b4c5862017-09-04 15:13:25 +0200254/* gb_proxy_vty .c */
255
256int gbproxy_vty_init(void);
257int gbproxy_parse_config(const char *config_file, struct gbproxy_config *cfg);
258
Daniel Willmann13404b72018-06-01 07:21:20 +0200259/* gb_proxy_ctrl.c */
260int gb_ctrl_cmds_install(void);
261
Neels Hofmeyr4b4c5862017-09-04 15:13:25 +0200262
263/* gb_proxy.c */
264int gbproxy_init_config(struct gbproxy_config *cfg);
265
266/* Main input function for Gb proxy */
Alexander Couzens951e1332020-09-22 13:21:46 +0200267int gbprox_rcvmsg(void *ctx, struct msgb *msg);
Neels Hofmeyr4b4c5862017-09-04 15:13:25 +0200268
269int gbprox_signal(unsigned int subsys, unsigned int signal,
270 void *handler_data, void *signal_data);
271
Alexander Couzens951e1332020-09-22 13:21:46 +0200272
273int gprs_ns2_prim_cb(struct osmo_prim_hdr *oph, void *ctx);
Neels Hofmeyr4b4c5862017-09-04 15:13:25 +0200274
275void gbprox_reset(struct gbproxy_config *cfg);
276
Neels Hofmeyr4b4c5862017-09-04 15:13:25 +0200277/* Peer handling */
Harald Weltee5209642020-12-05 19:59:45 +0100278#define NSE_F_SGSN 0x0001
279#define NSE_F_BSS 0x0002
280
281struct gbproxy_bvc *gbproxy_bvc_by_bvci(struct gbproxy_nse *nse, uint16_t bvci);
Harald Welte560bdb32020-12-04 22:24:47 +0100282struct gbproxy_bvc *gbproxy_bvc_alloc(struct gbproxy_nse *nse, uint16_t bvci);
283void gbproxy_bvc_free(struct gbproxy_bvc *bvc);
Harald Weltee5209642020-12-05 19:59:45 +0100284int gbproxy_cleanup_bvcs(struct gbproxy_nse *nse, uint16_t bvci);
285
Philipp Maiere4597ec2021-02-09 16:02:00 +0100286struct gbproxy_cell *gbproxy_cell_alloc(struct gbproxy_config *cfg, uint16_t bvci, const struct gprs_ra_id *raid, uint16_t cid);
Harald Weltee5209642020-12-05 19:59:45 +0100287struct gbproxy_cell *gbproxy_cell_by_bvci(struct gbproxy_config *cfg, uint16_t bvci);
Daniel Willmannfccbef02021-01-19 17:59:19 +0100288struct gbproxy_cell *gbproxy_cell_by_cellid(struct gbproxy_config *cfg, const struct gprs_ra_id *raid, uint16_t cid);
Harald Weltee5209642020-12-05 19:59:45 +0100289void gbproxy_cell_free(struct gbproxy_cell *cell);
290bool gbproxy_cell_add_sgsn_bvc(struct gbproxy_cell *cell, struct gbproxy_bvc *bvc);
Daniel Willmanna631a3a2021-07-14 18:10:16 +0200291void gbproxy_cell_cleanup_bvc(struct gbproxy_cell *cell, struct gbproxy_bvc *bvc);
Neels Hofmeyr4b4c5862017-09-04 15:13:25 +0200292
Daniel Willmanne50550e2020-11-26 18:19:21 +0100293/* NSE handling */
Harald Weltee5209642020-12-05 19:59:45 +0100294struct gbproxy_nse *gbproxy_nse_alloc(struct gbproxy_config *cfg, uint16_t nsei, bool sgsn_facing);
Daniel Willmanne50550e2020-11-26 18:19:21 +0100295void gbproxy_nse_free(struct gbproxy_nse *nse);
Harald Weltee5209642020-12-05 19:59:45 +0100296struct gbproxy_nse *gbproxy_nse_by_nsei(struct gbproxy_config *cfg, uint16_t nsei, uint32_t flags);
297struct gbproxy_nse *gbproxy_nse_by_nsei_or_new(struct gbproxy_config *cfg, uint16_t nsei, bool sgsn_facing);
Daniel Willmann77493b12020-12-29 21:13:31 +0100298struct gbproxy_nse *gbproxy_nse_by_tlli(struct gbproxy_config *cfg, uint32_t tlli);
Daniel Willmann361d0b52021-07-09 17:44:30 +0200299struct gbproxy_nse *gbproxy_nse_by_imsi(struct gbproxy_config *cfg, const char *imsi, enum cache_usage_type usage);
Daniel Willmann77493b12020-12-29 21:13:31 +0100300
301/* TLLI cache */
302void gbproxy_tlli_cache_update(struct gbproxy_nse *nse, uint32_t tlli);
303void gbproxy_tlli_cache_remove(struct gbproxy_config *cfg, uint32_t tlli);
304int gbproxy_tlli_cache_cleanup(struct gbproxy_config *cfg);
Daniel Willmanne50550e2020-11-26 18:19:21 +0100305
Daniel Willmannc8a50092021-01-17 13:11:41 +0100306/* IMSI cache */
Daniel Willmann361d0b52021-07-09 17:44:30 +0200307void gbproxy_imsi_cache_update(struct gbproxy_nse *nse, const char *imsi, enum cache_usage_type usage);
308void gbproxy_imsi_cache_remove(struct gbproxy_config *cfg, const char *imsi, enum cache_usage_type usage);
Daniel Willmannc8a50092021-01-17 13:11:41 +0100309int gbproxy_imsi_cache_cleanup(struct gbproxy_config *cfg);
310
Daniel Willmannee834af2020-12-14 16:22:39 +0100311/* SGSN handling */
Daniel Willmanna648f3c2020-12-28 18:07:27 +0100312struct gbproxy_sgsn *gbproxy_sgsn_alloc(struct gbproxy_config *cfg, uint16_t nsei, const char *name);
Daniel Willmannee834af2020-12-14 16:22:39 +0100313void gbproxy_sgsn_free(struct gbproxy_sgsn *sgsn);
Daniel Willmanna648f3c2020-12-28 18:07:27 +0100314struct gbproxy_sgsn *gbproxy_sgsn_by_name(struct gbproxy_config *cfg, const char *name);
Daniel Willmannee834af2020-12-14 16:22:39 +0100315struct gbproxy_sgsn *gbproxy_sgsn_by_nsei(struct gbproxy_config *cfg, uint16_t nsei);
316struct gbproxy_sgsn *gbproxy_sgsn_by_nsei_or_new(struct gbproxy_config *cfg, uint16_t nsei);
317struct gbproxy_sgsn *gbproxy_sgsn_by_nri(struct gbproxy_config *cfg, uint16_t nri, bool *null_nri);
Daniel Willmannd4ab1f92020-12-21 18:53:55 +0100318struct gbproxy_sgsn *gbproxy_sgsn_by_tlli(struct gbproxy_config *cfg, struct gbproxy_sgsn *sgsn_avoid,
319 uint32_t tlli);
Daniel Willmann37518b32021-05-27 18:13:36 +0200320struct gbproxy_sgsn *gbproxy_sgsn_by_available(struct gbproxy_config *cfg);