<p>daniel has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/osmo-sgsn/+/21406">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">gbproxy: Add NSE peer that can have multiple gbproxy_peers<br><br>We want this level of indirection to support multiple BVCs per NSE. The<br>current code assumes that an NSE only has one BVC which breaks messages<br>on the signalling BVC which should only be sent once to an NSE<br>regardless of the number of BVCs it contains.<br><br>Change-Id: I97cc6c8f8c0f1b91577ab8f679c4ae217cc88076<br>Related: SYS#5226<br>---<br>M include/osmocom/sgsn/gb_proxy.h<br>M src/gbproxy/gb_proxy.c<br>M src/gbproxy/gb_proxy_ctrl.c<br>M src/gbproxy/gb_proxy_patch.c<br>M src/gbproxy/gb_proxy_peer.c<br>M src/gbproxy/gb_proxy_tlli.c<br>M src/gbproxy/gb_proxy_vty.c<br>M tests/gbproxy/gbproxy_test.c<br>8 files changed, 315 insertions(+), 114 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/osmo-sgsn refs/changes/06/21406/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/osmocom/sgsn/gb_proxy.h b/include/osmocom/sgsn/gb_proxy.h</span><br><span>index 4466f15..ab9f3f3 100644</span><br><span>--- a/include/osmocom/sgsn/gb_proxy.h</span><br><span>+++ b/include/osmocom/sgsn/gb_proxy.h</span><br><span>@@ -15,6 +15,13 @@</span><br><span> </span><br><span> #define GBPROXY_INIT_VU_GEN_TX 256</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/* Iterate through all BVCs of all NSEs</span><br><span style="color: hsl(120, 100%, 40%);">+ * Since these are two for loops the break keyword</span><br><span style="color: hsl(120, 100%, 40%);">+ * doesn't work as expected (only breaks out of the inner loop) */</span><br><span style="color: hsl(120, 100%, 40%);">+#define gbproxy_for_each_bvc(cfg, nse, bvc) \</span><br><span style="color: hsl(120, 100%, 40%);">+ llist_for_each_entry(nse, &cfg->nse_peers, list) \</span><br><span style="color: hsl(120, 100%, 40%);">+ llist_for_each_entry(bvc, &nse->bts_peers, list)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> struct rate_ctr_group;</span><br><span> struct gprs_gb_parse_context;</span><br><span> struct tlv_parsed;</span><br><span>@@ -99,7 +106,7 @@</span><br><span> struct gprs_ns2_inst *nsi;</span><br><span> </span><br><span> /* Linked list of all Gb peers (except SGSN) */</span><br><span style="color: hsl(0, 100%, 40%);">- struct llist_head bts_peers;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct llist_head nse_peers;</span><br><span> </span><br><span> /* Counter */</span><br><span> struct rate_ctr_group *ctrg;</span><br><span>@@ -143,24 +150,23 @@</span><br><span> int logical_link_count;</span><br><span> };</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/* one peer at NS level that we interact with (BSS/PCU) */</span><br><span style="color: hsl(120, 100%, 40%);">+/* One BVC inside an NSE */</span><br><span> struct gbproxy_peer {</span><br><span style="color: hsl(0, 100%, 40%);">- /* linked to gbproxy_config.bts_peers */</span><br><span style="color: hsl(120, 100%, 40%);">+ /* linked to gbproxy_peer.bts_peers */</span><br><span> struct llist_head list;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- /* point back to the config */</span><br><span style="color: hsl(0, 100%, 40%);">- struct gbproxy_config *cfg;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* NSEI of the peer entity */</span><br><span style="color: hsl(0, 100%, 40%);">- uint16_t nsei;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* The peer this BVC belongs to */</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gbproxy_nse *nse;</span><br><span> </span><br><span> /* BVCI used for Point-to-Point to this peer */</span><br><span> uint16_t bvci;</span><br><span style="color: hsl(0, 100%, 40%);">- bool blocked;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- /* Routeing Area that this peer is part of (raw 04.08 encoding) */</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Routing Area that this peer is part of (raw 04.08 encoding) */</span><br><span> uint8_t ra[6];</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ /* true if this BVC is blocked */</span><br><span style="color: hsl(120, 100%, 40%);">+ bool blocked;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* Counter */</span><br><span> struct rate_ctr_group *ctrg;</span><br><span> </span><br><span>@@ -171,6 +177,21 @@</span><br><span> struct osmo_timer_list clean_stale_timer;</span><br><span> };</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/* one peer at NS level that we interact with (BSS/PCU) */</span><br><span style="color: hsl(120, 100%, 40%);">+struct gbproxy_nse {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* linked to gbproxy_config.bts_peers */</span><br><span style="color: hsl(120, 100%, 40%);">+ struct llist_head list;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* point back to the config */</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gbproxy_config *cfg;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* NSEI of the peer entity */</span><br><span style="color: hsl(120, 100%, 40%);">+ uint16_t nsei;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* List of all BVCs in this NSE */</span><br><span style="color: hsl(120, 100%, 40%);">+ struct llist_head bts_peers;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> struct gbproxy_tlli_state {</span><br><span> /* currently active TLLI */</span><br><span> uint32_t current;</span><br><span>@@ -328,8 +349,14 @@</span><br><span> struct gbproxy_config *cfg, const uint8_t *la);</span><br><span> struct gbproxy_peer *gbproxy_peer_by_bssgp_tlv(</span><br><span> struct gbproxy_config *cfg, struct tlv_parsed *tp);</span><br><span style="color: hsl(0, 100%, 40%);">-struct gbproxy_peer *gbproxy_peer_alloc(struct gbproxy_config *cfg, uint16_t bvci);</span><br><span style="color: hsl(120, 100%, 40%);">+struct gbproxy_peer *gbproxy_peer_alloc(struct gbproxy_nse *nse, uint16_t bvci);</span><br><span> void gbproxy_peer_free(struct gbproxy_peer *peer);</span><br><span> int gbproxy_cleanup_peers(struct gbproxy_config *cfg, uint16_t nsei, uint16_t bvci);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/* NSE handling */</span><br><span style="color: hsl(120, 100%, 40%);">+struct gbproxy_nse *gbproxy_nse_alloc(struct gbproxy_config *cfg, uint16_t nsei);</span><br><span style="color: hsl(120, 100%, 40%);">+void gbproxy_nse_free(struct gbproxy_nse *nse);</span><br><span style="color: hsl(120, 100%, 40%);">+struct gbproxy_nse *gbproxy_nse_by_nsei(struct gbproxy_config *cfg, uint16_t nsei);</span><br><span style="color: hsl(120, 100%, 40%);">+struct gbproxy_nse *gbproxy_nse_by_nsei_or_new(struct gbproxy_config *cfg, uint16_t nsei);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #endif</span><br><span>diff --git a/src/gbproxy/gb_proxy.c b/src/gbproxy/gb_proxy.c</span><br><span>index 39b9ffd..d313255 100644</span><br><span>--- a/src/gbproxy/gb_proxy.c</span><br><span>+++ b/src/gbproxy/gb_proxy.c</span><br><span>@@ -84,10 +84,12 @@</span><br><span> </span><br><span> static int check_peer_nsei(struct gbproxy_peer *peer, uint16_t nsei)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- if (peer->nsei != nsei) {</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(peer->nse);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (peer->nse->nsei != nsei) {</span><br><span> LOGP(DGPRS, LOGL_NOTICE, "Peer entry doesn't match current NSEI "</span><br><span> "BVCI=%u via NSEI=%u (expected NSEI=%u)\n",</span><br><span style="color: hsl(0, 100%, 40%);">- peer->bvci, nsei, peer->nsei);</span><br><span style="color: hsl(120, 100%, 40%);">+ peer->bvci, nsei, peer->nse->nsei);</span><br><span> rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_INV_NSEI]);</span><br><span> return 0;</span><br><span> }</span><br><span>@@ -195,6 +197,9 @@</span><br><span> struct gbproxy_patch_state *state = &peer->patch_state;</span><br><span> const struct osmo_plmn_id old_plmn = state->local_plmn;</span><br><span> struct gprs_ra_id raid;</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(peer->nse);</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gbproxy_config *cfg = peer->nse->cfg;</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(cfg);</span><br><span> </span><br><span> if (!raid_enc)</span><br><span> return;</span><br><span>@@ -202,15 +207,15 @@</span><br><span> gsm48_parse_ra(&raid, raid_enc);</span><br><span> </span><br><span> /* save source side MCC/MNC */</span><br><span style="color: hsl(0, 100%, 40%);">- if (!peer->cfg->core_plmn.mcc || raid.mcc == peer->cfg->core_plmn.mcc) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!cfg->core_plmn.mcc || raid.mcc == cfg->core_plmn.mcc) {</span><br><span> state->local_plmn.mcc = 0;</span><br><span> } else {</span><br><span> state->local_plmn.mcc = raid.mcc;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (!peer->cfg->core_plmn.mnc</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!cfg->core_plmn.mnc</span><br><span> || !osmo_mnc_cmp(raid.mnc, raid.mnc_3_digits,</span><br><span style="color: hsl(0, 100%, 40%);">- peer->cfg->core_plmn.mnc, peer->cfg->core_plmn.mnc_3_digits)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ cfg->core_plmn.mnc, cfg->core_plmn.mnc_3_digits)) {</span><br><span> state->local_plmn.mnc = 0;</span><br><span> state->local_plmn.mnc_3_digits = false;</span><br><span> } else {</span><br><span>@@ -226,7 +231,7 @@</span><br><span> "" : "de",</span><br><span> log_text,</span><br><span> osmo_plmn_name(&state->local_plmn),</span><br><span style="color: hsl(0, 100%, 40%);">- osmo_plmn_name2(&peer->cfg->core_plmn));</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_plmn_name2(&cfg->core_plmn));</span><br><span> }</span><br><span> </span><br><span> uint32_t gbproxy_make_bss_ptmsi(struct gbproxy_peer *peer,</span><br><span>@@ -234,7 +239,7 @@</span><br><span> {</span><br><span> uint32_t bss_ptmsi;</span><br><span> int max_retries = 23, rc = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- if (!peer->cfg->patch_ptmsi) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!peer->nse->cfg->patch_ptmsi) {</span><br><span> bss_ptmsi = sgsn_ptmsi;</span><br><span> } else {</span><br><span> do {</span><br><span>@@ -263,7 +268,7 @@</span><br><span> {</span><br><span> uint32_t sgsn_tlli;</span><br><span> int max_retries = 23, rc = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- if (!peer->cfg->patch_ptmsi) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!peer->nse->cfg->patch_ptmsi) {</span><br><span> sgsn_tlli = bss_tlli;</span><br><span> } else if (link_info->sgsn_tlli.ptmsi != GSM_RESERVED_TMSI &&</span><br><span> gprs_tlli_type(bss_tlli) == TLLI_FOREIGN) {</span><br><span>@@ -330,6 +335,9 @@</span><br><span> {</span><br><span> int rc;</span><br><span> struct msgb *stored_msg;</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(peer->nse);</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gbproxy_config *cfg = peer->nse->cfg;</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(cfg);</span><br><span> </span><br><span> /* Patch and flush stored messages towards the SGSN */</span><br><span> while ((stored_msg = msgb_dequeue_count(&link_info->stored_msgs,</span><br><span>@@ -355,7 +363,7 @@</span><br><span> return -1;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- rc = gbprox_relay2sgsn(peer->cfg, stored_msg,</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = gbprox_relay2sgsn(cfg, stored_msg,</span><br><span> msgb_bvci(stored_msg), link_info->sgsn_nsei);</span><br><span> </span><br><span> if (rc < 0)</span><br><span>@@ -425,6 +433,9 @@</span><br><span> struct gprs_gb_parse_context *parse_ctx)</span><br><span> {</span><br><span> struct msgb *stored_msg;</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(peer->nse);</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gbproxy_config *cfg = peer->nse->cfg;</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(cfg);</span><br><span> </span><br><span> if (!link_info)</span><br><span> return 1;</span><br><span>@@ -493,9 +504,9 @@</span><br><span> /* The message cannot be processed since the IMSI is still missing */</span><br><span> </span><br><span> /* If queue is getting too large, drop oldest msgb before adding new one */</span><br><span style="color: hsl(0, 100%, 40%);">- if (peer->cfg->stored_msgs_max_len > 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cfg->stored_msgs_max_len > 0) {</span><br><span> int exceeded_max_len = link_info->stored_msgs_len</span><br><span style="color: hsl(0, 100%, 40%);">- + 1 - peer->cfg->stored_msgs_max_len;</span><br><span style="color: hsl(120, 100%, 40%);">+ + 1 - cfg->stored_msgs_max_len;</span><br><span> </span><br><span> for (; exceeded_max_len > 0; exceeded_max_len--) {</span><br><span> struct msgb *msgb_drop;</span><br><span>@@ -806,18 +817,22 @@</span><br><span> static int gbprox_relay2peer(struct msgb *old_msg, struct gbproxy_peer *peer,</span><br><span> uint16_t ns_bvci)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gbproxy_nse *nse = peer->nse;</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(nse);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(nse->cfg);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* create a copy of the message so the old one can</span><br><span> * be free()d safely when we return from gbprox_rcvmsg() */</span><br><span style="color: hsl(0, 100%, 40%);">- struct gprs_ns2_inst *nsi = peer->cfg->nsi;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gprs_ns2_inst *nsi = nse->cfg->nsi;</span><br><span> struct osmo_gprs_ns2_prim nsp = {};</span><br><span> struct msgb *msg = bssgp_msgb_copy(old_msg, "msgb_relay2peer");</span><br><span> int rc;</span><br><span> </span><br><span> DEBUGP(DGPRS, "NSEI=%u proxying SGSN->BSS (NS_BVCI=%u, NSEI=%u)\n",</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_nsei(msg), ns_bvci, peer->nsei);</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_nsei(msg), ns_bvci, nse->nsei);</span><br><span> </span><br><span> nsp.bvci = ns_bvci;</span><br><span style="color: hsl(0, 100%, 40%);">- nsp.nsei = peer->nsei;</span><br><span style="color: hsl(120, 100%, 40%);">+ nsp.nsei = nse->nsei;</span><br><span> </span><br><span> /* Strip the old NS header, it will be replaced with a new one */</span><br><span> strip_ns_hdr(msg);</span><br><span>@@ -1034,6 +1049,14 @@</span><br><span> LOGP(DGPRS, LOGL_INFO, "NSEI=%u Rx BVC RESET (BVCI=%u)\n",</span><br><span> nsei, bvci);</span><br><span> if (bvci == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gbproxy_nse *nse;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Ensure the NSE peer is there and clear all PtP BVCs */</span><br><span style="color: hsl(120, 100%, 40%);">+ nse = gbproxy_nse_by_nsei_or_new(cfg, nsei);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!nse)</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DGPRS, LOGL_ERROR, "Could not allocate NSE\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ gbproxy_cleanup_peers(cfg, nsei, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* FIXME: only do this if SGSN is alive! */</span><br><span> LOGP(DGPRS, LOGL_INFO, "NSEI=%u Tx fake "</span><br><span> "BVC RESET ACK of BVCI=0\n", nsei);</span><br><span>@@ -1042,16 +1065,34 @@</span><br><span> }</span><br><span> from_peer = gbproxy_peer_by_bvci(cfg, bvci);</span><br><span> if (!from_peer) {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gbproxy_nse *nse = gbproxy_nse_by_nsei(cfg, nsei);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!nse) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DGPRS, LOGL_NOTICE, "Got PtP BVC reset before signalling reset for "</span><br><span style="color: hsl(120, 100%, 40%);">+ "BVCI=%u NSEI=%u\n", bvci, nsei);</span><br><span style="color: hsl(120, 100%, 40%);">+ return bssgp_tx_status(BSSGP_CAUSE_PDU_INCOMP_STATE, NULL, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span> /* if a PTP-BVC is reset, and we don't know that</span><br><span> * PTP-BVCI yet, we should allocate a new peer */</span><br><span> LOGP(DGPRS, LOGL_INFO, "Allocationg new peer for BVCI=%u via NSEI=%u\n", bvci, nsei);</span><br><span style="color: hsl(0, 100%, 40%);">- from_peer = gbproxy_peer_alloc(cfg, bvci);</span><br><span style="color: hsl(120, 100%, 40%);">+ from_peer = gbproxy_peer_alloc(nse, bvci);</span><br><span> OSMO_ASSERT(from_peer);</span><br><span style="color: hsl(0, 100%, 40%);">- from_peer->nsei = nsei;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (!check_peer_nsei(from_peer, nsei))</span><br><span style="color: hsl(0, 100%, 40%);">- from_peer->nsei = nsei;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Could have moved to a different NSE */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!check_peer_nsei(from_peer, nsei)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gbproxy_nse *nse_old = from_peer->nse;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gbproxy_nse *nse_new = gbproxy_nse_by_nsei(cfg, nsei);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!nse_new) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DGPRS, LOGL_NOTICE, "Got PtP BVC reset before signalling reset for "</span><br><span style="color: hsl(120, 100%, 40%);">+ "BVCI=%u NSEI=%u\n", bvci, nsei);</span><br><span style="color: hsl(120, 100%, 40%);">+ return bssgp_tx_status(BSSGP_CAUSE_PDU_INCOMP_STATE, NULL, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DGPRS, LOGL_NOTICE, "Peer for BVCI=%u moved from NSEI=%u to NSEI=%u\n", bvci, nse_old->nsei, nsei);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Move peer to different NSE */</span><br><span style="color: hsl(120, 100%, 40%);">+ llist_del(&from_peer->list);</span><br><span style="color: hsl(120, 100%, 40%);">+ llist_add(&from_peer->list, &nse_new->bts_peers);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span> </span><br><span> if (TLVP_PRESENT(&tp, BSSGP_IE_CELL_ID)) {</span><br><span> struct gprs_ra_id raid;</span><br><span>@@ -1098,10 +1139,13 @@</span><br><span> static int gbprox_rx_paging(struct gbproxy_config *cfg, struct msgb *msg, struct tlv_parsed *tp,</span><br><span> uint32_t nsei, uint16_t ns_bvci)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gbproxy_nse *nse;</span><br><span> struct gbproxy_peer *peer;</span><br><span> unsigned int n_peers = 0;</span><br><span> int errctr = GBPROX_GLOB_CTR_PROTO_ERR_SGSN;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ /* FIXME: Handle paging logic to only page each matching NSE */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> LOGP(DGPRS, LOGL_INFO, "NSEI=%u(SGSN) BSSGP PAGING ",</span><br><span> nsei);</span><br><span> if (TLVP_PRESENT(tp, BSSGP_IE_BVCI)) {</span><br><span>@@ -1119,7 +1163,7 @@</span><br><span> } else if (TLVP_PRESENT(tp, BSSGP_IE_ROUTEING_AREA)) {</span><br><span> errctr = GBPROX_GLOB_CTR_INV_RAI;</span><br><span> /* iterate over all peers and dispatch the paging to each matching one */</span><br><span style="color: hsl(0, 100%, 40%);">- llist_for_each_entry(peer, &cfg->bts_peers, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+ gbproxy_for_each_bvc(cfg, nse, peer) {</span><br><span> if (!memcmp(peer->ra, TLVP_VAL(tp, BSSGP_IE_ROUTEING_AREA), 6)) {</span><br><span> LOGPC(DGPRS, LOGL_INFO, "routing by RAI to peer BVCI=%u\n", peer->bvci);</span><br><span> gbprox_relay2peer(msg, peer, ns_bvci);</span><br><span>@@ -1129,7 +1173,7 @@</span><br><span> } else if (TLVP_PRESENT(tp, BSSGP_IE_LOCATION_AREA)) {</span><br><span> errctr = GBPROX_GLOB_CTR_INV_LAI;</span><br><span> /* iterate over all peers and dispatch the paging to each matching one */</span><br><span style="color: hsl(0, 100%, 40%);">- llist_for_each_entry(peer, &cfg->bts_peers, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+ gbproxy_for_each_bvc(cfg, nse, peer) {</span><br><span> if (!memcmp(peer->ra, TLVP_VAL(tp, BSSGP_IE_LOCATION_AREA), 5)) {</span><br><span> LOGPC(DGPRS, LOGL_INFO, "routing by LAI to peer BVCI=%u\n", peer->bvci);</span><br><span> gbprox_relay2peer(msg, peer, ns_bvci);</span><br><span>@@ -1138,7 +1182,7 @@</span><br><span> }</span><br><span> } else if (TLVP_PRESENT(tp, BSSGP_IE_BSS_AREA_ID)) {</span><br><span> /* iterate over all peers and dispatch the paging to each matching one */</span><br><span style="color: hsl(0, 100%, 40%);">- llist_for_each_entry(peer, &cfg->bts_peers, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+ gbproxy_for_each_bvc(cfg, nse, peer) {</span><br><span> LOGPC(DGPRS, LOGL_INFO, "broadcasting to peer BVCI=%u\n", peer->bvci);</span><br><span> gbprox_relay2peer(msg, peer, ns_bvci);</span><br><span> n_peers++;</span><br><span>@@ -1165,6 +1209,7 @@</span><br><span> struct msgb *msg, struct tlv_parsed *tp,</span><br><span> uint32_t nsei, uint16_t ns_bvci)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gbproxy_nse *nse;</span><br><span> struct gbproxy_peer *peer;</span><br><span> uint16_t ptp_bvci;</span><br><span> </span><br><span>@@ -1195,7 +1240,7 @@</span><br><span> * from the SGSN. As the signalling BVCI is shared</span><br><span> * among all the BSS's that we multiplex, it needs to</span><br><span> * be relayed */</span><br><span style="color: hsl(0, 100%, 40%);">- llist_for_each_entry(peer, &cfg->bts_peers, list)</span><br><span style="color: hsl(120, 100%, 40%);">+ gbproxy_for_each_bvc(cfg, nse, peer)</span><br><span> gbprox_relay2peer(msg, peer, ns_bvci);</span><br><span> </span><br><span> return 0;</span><br><span>@@ -1445,7 +1490,8 @@</span><br><span> rate_ctr_inc(&cfg->ctrg-></span><br><span> ctr[GBPROX_GLOB_CTR_RESTART_RESET_SGSN]);</span><br><span> } else {</span><br><span style="color: hsl(0, 100%, 40%);">- /* bss became unavailable */</span><br><span style="color: hsl(120, 100%, 40%);">+ /* bss became unavailable</span><br><span style="color: hsl(120, 100%, 40%);">+ * TODO: Block all BVC belonging to that NSE */</span><br><span> peer = gbproxy_peer_by_nsei(cfg, nsp->nsei);</span><br><span> if (!peer) {</span><br><span> /* TODO: use primitive name + status cause name */</span><br><span>@@ -1516,10 +1562,15 @@</span><br><span> </span><br><span> void gbprox_reset(struct gbproxy_config *cfg)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gbproxy_nse *nse, *ntmp;</span><br><span> struct gbproxy_peer *peer, *tmp;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- llist_for_each_entry_safe(peer, tmp, &cfg->bts_peers, list)</span><br><span style="color: hsl(0, 100%, 40%);">- gbproxy_peer_free(peer);</span><br><span style="color: hsl(120, 100%, 40%);">+ llist_for_each_entry_safe(nse, ntmp, &cfg->nse_peers, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+ llist_for_each_entry_safe(peer, tmp, &nse->bts_peers, list)</span><br><span style="color: hsl(120, 100%, 40%);">+ gbproxy_peer_free(peer);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ gbproxy_nse_free(nse);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span> </span><br><span> rate_ctr_group_free(cfg->ctrg);</span><br><span> gbproxy_init_config(cfg);</span><br><span>@@ -1529,7 +1580,7 @@</span><br><span> {</span><br><span> struct timespec tp;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- INIT_LLIST_HEAD(&cfg->bts_peers);</span><br><span style="color: hsl(120, 100%, 40%);">+ INIT_LLIST_HEAD(&cfg->nse_peers);</span><br><span> cfg->ctrg = rate_ctr_group_alloc(tall_sgsn_ctx, &global_ctrg_desc, 0);</span><br><span> if (!cfg->ctrg) {</span><br><span> LOGP(DGPRS, LOGL_ERROR, "Cannot allocate global counter group!\n");</span><br><span>diff --git a/src/gbproxy/gb_proxy_ctrl.c b/src/gbproxy/gb_proxy_ctrl.c</span><br><span>index 9577383..28b36a8 100644</span><br><span>--- a/src/gbproxy/gb_proxy_ctrl.c</span><br><span>+++ b/src/gbproxy/gb_proxy_ctrl.c</span><br><span>@@ -55,7 +55,7 @@</span><br><span> struct gbproxy_config *cfg = data;</span><br><span> struct gprs_ns2_inst *nsi = cfg->nsi;</span><br><span> struct gprs_ns2_nse *nse;</span><br><span style="color: hsl(0, 100%, 40%);">- struct gbproxy_peer *peer;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gbproxy_nse *nse_peer;</span><br><span> </span><br><span> cmd->reply = talloc_strdup(cmd, "");</span><br><span> </span><br><span>@@ -69,8 +69,8 @@</span><br><span> gprs_ns2_nse_foreach_nsvc(nse, &ctrl_nsvc_state_cb, cmd);</span><br><span> </span><br><span> /* NS-VCs for BSS peers */</span><br><span style="color: hsl(0, 100%, 40%);">- llist_for_each_entry(peer, &cfg->bts_peers, list) {</span><br><span style="color: hsl(0, 100%, 40%);">- nse = gprs_ns2_nse_by_nsei(nsi, peer->nsei);</span><br><span style="color: hsl(120, 100%, 40%);">+ llist_for_each_entry(nse_peer, &cfg->nse_peers, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+ nse = gprs_ns2_nse_by_nsei(nsi, nse_peer->nsei);</span><br><span> if (nse)</span><br><span> gprs_ns2_nse_foreach_nsvc(nse, &ctrl_nsvc_state_cb, cmd);</span><br><span> }</span><br><span>@@ -83,16 +83,17 @@</span><br><span> static int get_gbproxy_state(struct ctrl_cmd *cmd, void *data)</span><br><span> {</span><br><span> struct gbproxy_config *cfg = data;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gbproxy_nse *nse_peer;</span><br><span> struct gbproxy_peer *peer;</span><br><span> </span><br><span> cmd->reply = talloc_strdup(cmd, "");</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- llist_for_each_entry(peer, &cfg->bts_peers, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+ gbproxy_for_each_bvc(cfg, nse_peer, peer) {</span><br><span> struct gprs_ra_id raid;</span><br><span> gsm48_parse_ra(&raid, peer->ra);</span><br><span> </span><br><span> cmd->reply = talloc_asprintf_append(cmd->reply, "%u,%u,%u,%u,%u,%u,%s\n",</span><br><span style="color: hsl(0, 100%, 40%);">- peer->nsei, peer->bvci,</span><br><span style="color: hsl(120, 100%, 40%);">+ nse_peer->nsei, peer->bvci,</span><br><span> raid.mcc, raid.mnc,</span><br><span> raid.lac, raid.rac,</span><br><span> peer->blocked ? "BLOCKED" : "UNBLOCKED");</span><br><span>@@ -106,9 +107,14 @@</span><br><span> static int get_num_peers(struct ctrl_cmd *cmd, void *data)</span><br><span> {</span><br><span> struct gbproxy_config *cfg = data;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gbproxy_nse *nse_peer;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t count = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ llist_for_each_entry(nse_peer, &cfg->nse_peers, list)</span><br><span style="color: hsl(120, 100%, 40%);">+ count += llist_count(&nse_peer->bts_peers);</span><br><span> </span><br><span> cmd->reply = talloc_strdup(cmd, "");</span><br><span style="color: hsl(0, 100%, 40%);">- cmd->reply = talloc_asprintf_append(cmd->reply, "%u", llist_count(&cfg->bts_peers));</span><br><span style="color: hsl(120, 100%, 40%);">+ cmd->reply = talloc_asprintf_append(cmd->reply, "%u", count);</span><br><span> </span><br><span> return CTRL_CMD_REPLY;</span><br><span> }</span><br><span>diff --git a/src/gbproxy/gb_proxy_patch.c b/src/gbproxy/gb_proxy_patch.c</span><br><span>index 9c70d3f..6601657 100644</span><br><span>--- a/src/gbproxy/gb_proxy_patch.c</span><br><span>+++ b/src/gbproxy/gb_proxy_patch.c</span><br><span>@@ -44,6 +44,10 @@</span><br><span> GBPROX_PEER_CTR_RAID_PATCHED_SGSN :</span><br><span> GBPROX_PEER_CTR_RAID_PATCHED_BSS;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(peer->nse);</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gbproxy_config *cfg = peer->nse->cfg;</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(cfg);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> if (!state->local_plmn.mcc || !state->local_plmn.mnc)</span><br><span> return;</span><br><span> </span><br><span>@@ -58,11 +62,11 @@</span><br><span> if (!to_bss) {</span><br><span> /* BSS -> SGSN */</span><br><span> if (state->local_plmn.mcc)</span><br><span style="color: hsl(0, 100%, 40%);">- raid.mcc = peer->cfg->core_plmn.mcc;</span><br><span style="color: hsl(120, 100%, 40%);">+ raid.mcc = cfg->core_plmn.mcc;</span><br><span> </span><br><span> if (state->local_plmn.mnc) {</span><br><span style="color: hsl(0, 100%, 40%);">- raid.mnc = peer->cfg->core_plmn.mnc;</span><br><span style="color: hsl(0, 100%, 40%);">- raid.mnc_3_digits = peer->cfg->core_plmn.mnc_3_digits;</span><br><span style="color: hsl(120, 100%, 40%);">+ raid.mnc = cfg->core_plmn.mnc;</span><br><span style="color: hsl(120, 100%, 40%);">+ raid.mnc_3_digits = cfg->core_plmn.mnc_3_digits;</span><br><span> }</span><br><span> } else {</span><br><span> /* SGSN -> BSS */</span><br><span>@@ -100,11 +104,14 @@</span><br><span> </span><br><span> size_t apn_len = hdr->apn_len;</span><br><span> uint8_t *apn = hdr->apn;</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(peer->nse);</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gbproxy_config *cfg = peer->nse->cfg;</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(cfg);</span><br><span> </span><br><span> OSMO_ASSERT(apn_ie_len == apn_len + sizeof(struct apn_ie_hdr));</span><br><span> OSMO_ASSERT(apn_ie_len > 2 && apn_ie_len <= 102);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (peer->cfg->core_apn_size == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cfg->core_apn_size == 0) {</span><br><span> char str1[110];</span><br><span> /* Remove the IE */</span><br><span> LOGP(DGPRS, LOGL_DEBUG,</span><br><span>@@ -119,20 +126,20 @@</span><br><span> char str1[110];</span><br><span> char str2[110];</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(peer->cfg->core_apn_size <= 100);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(cfg->core_apn_size <= 100);</span><br><span> </span><br><span> LOGP(DGPRS, LOGL_DEBUG,</span><br><span> "Patching %s to SGSN: "</span><br><span> "Replacing APN '%s' -> '%s'\n",</span><br><span> log_text,</span><br><span> osmo_apn_to_str(str1, apn, apn_len),</span><br><span style="color: hsl(0, 100%, 40%);">- osmo_apn_to_str(str2, peer->cfg->core_apn,</span><br><span style="color: hsl(0, 100%, 40%);">- peer->cfg->core_apn_size));</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_apn_to_str(str2, cfg->core_apn,</span><br><span style="color: hsl(120, 100%, 40%);">+ cfg->core_apn_size));</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- *new_apn_ie_len = peer->cfg->core_apn_size + 2;</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_resize_area(msg, apn, apn_len, peer->cfg->core_apn_size);</span><br><span style="color: hsl(0, 100%, 40%);">- memcpy(apn, peer->cfg->core_apn, peer->cfg->core_apn_size);</span><br><span style="color: hsl(0, 100%, 40%);">- hdr->apn_len = peer->cfg->core_apn_size;</span><br><span style="color: hsl(120, 100%, 40%);">+ *new_apn_ie_len = cfg->core_apn_size + 2;</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_resize_area(msg, apn, apn_len, cfg->core_apn_size);</span><br><span style="color: hsl(120, 100%, 40%);">+ memcpy(apn, cfg->core_apn, cfg->core_apn_size);</span><br><span style="color: hsl(120, 100%, 40%);">+ hdr->apn_len = cfg->core_apn_size;</span><br><span> }</span><br><span> </span><br><span> rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_APN_PATCHED]);</span><br><span>@@ -207,10 +214,12 @@</span><br><span> struct gprs_llc_hdr_parsed *ghp = &parse_ctx->llc_hdr_parsed;</span><br><span> int have_patched = 0;</span><br><span> int fcs;</span><br><span style="color: hsl(0, 100%, 40%);">- struct gbproxy_config *cfg = peer->cfg;</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(peer->nse);</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gbproxy_config *cfg = peer->nse->cfg;</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(cfg);</span><br><span> </span><br><span> if (parse_ctx->ptmsi_enc && link_info &&</span><br><span style="color: hsl(0, 100%, 40%);">- !parse_ctx->old_raid_is_foreign && peer->cfg->patch_ptmsi) {</span><br><span style="color: hsl(120, 100%, 40%);">+ !parse_ctx->old_raid_is_foreign && cfg->patch_ptmsi) {</span><br><span> uint32_t ptmsi;</span><br><span> if (parse_ctx->to_bss)</span><br><span> ptmsi = link_info->tlli.ptmsi;</span><br><span>@@ -291,13 +300,16 @@</span><br><span> {</span><br><span> const char *err_info = NULL;</span><br><span> int err_ctr = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(peer->nse);</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gbproxy_config *cfg = peer->nse->cfg;</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(cfg);</span><br><span> </span><br><span> if (parse_ctx->bssgp_raid_enc)</span><br><span> gbproxy_patch_raid((struct gsm48_ra_id *)parse_ctx->bssgp_raid_enc, peer,</span><br><span> parse_ctx->to_bss, "BSSGP");</span><br><span> </span><br><span> if (parse_ctx->need_decryption &&</span><br><span style="color: hsl(0, 100%, 40%);">- (peer->cfg->patch_ptmsi || peer->cfg->core_apn)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ (cfg->patch_ptmsi || cfg->core_apn)) {</span><br><span> /* Patching LLC messages has been requested</span><br><span> * explicitly, but the message (including the</span><br><span> * type) is encrypted, so we possibly fail to</span><br><span>@@ -319,7 +331,7 @@</span><br><span> if (!link_info)</span><br><span> return;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (parse_ctx->tlli_enc && peer->cfg->patch_ptmsi) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (parse_ctx->tlli_enc && cfg->patch_ptmsi) {</span><br><span> uint32_t tlli = gbproxy_map_tlli(parse_ctx->tlli,</span><br><span> link_info, parse_ctx->to_bss);</span><br><span> </span><br><span>@@ -335,7 +347,7 @@</span><br><span> }</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (parse_ctx->bssgp_ptmsi_enc && peer->cfg->patch_ptmsi) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (parse_ctx->bssgp_ptmsi_enc && cfg->patch_ptmsi) {</span><br><span> uint32_t ptmsi;</span><br><span> if (parse_ctx->to_bss)</span><br><span> ptmsi = link_info->tlli.ptmsi;</span><br><span>diff --git a/src/gbproxy/gb_proxy_peer.c b/src/gbproxy/gb_proxy_peer.c</span><br><span>index 48482b6..0649d7c 100644</span><br><span>--- a/src/gbproxy/gb_proxy_peer.c</span><br><span>+++ b/src/gbproxy/gb_proxy_peer.c</span><br><span>@@ -20,6 +20,7 @@</span><br><span> *</span><br><span> */</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#include "osmocom/vty/command.h"</span><br><span> #include <osmocom/sgsn/gb_proxy.h></span><br><span> </span><br><span> #include <osmocom/sgsn/debug.h></span><br><span>@@ -81,47 +82,55 @@</span><br><span> };</span><br><span> </span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/* Find the gbprox_peer by its BVCI */</span><br><span style="color: hsl(120, 100%, 40%);">+/* Find the gbproxy_peer by its BVCI. There can only be one match */</span><br><span> struct gbproxy_peer *gbproxy_peer_by_bvci(struct gbproxy_config *cfg, uint16_t bvci)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gbproxy_nse *nse;</span><br><span> struct gbproxy_peer *peer;</span><br><span style="color: hsl(0, 100%, 40%);">- llist_for_each_entry(peer, &cfg->bts_peers, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ gbproxy_for_each_bvc(cfg, nse, peer) {</span><br><span> if (peer->bvci == bvci)</span><br><span> return peer;</span><br><span> }</span><br><span> return NULL;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/* Find the gbprox_peer by its NSEI */</span><br><span style="color: hsl(120, 100%, 40%);">+/* Find the gbproxy_peer by its NSEI */</span><br><span style="color: hsl(120, 100%, 40%);">+/* FIXME: Only returns the first peer, but we could have multiple on this nsei */</span><br><span> struct gbproxy_peer *gbproxy_peer_by_nsei(struct gbproxy_config *cfg,</span><br><span> uint16_t nsei)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- struct gbproxy_peer *peer;</span><br><span style="color: hsl(0, 100%, 40%);">- llist_for_each_entry(peer, &cfg->bts_peers, list) {</span><br><span style="color: hsl(0, 100%, 40%);">- if (peer->nsei == nsei)</span><br><span style="color: hsl(0, 100%, 40%);">- return peer;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gbproxy_nse *nse;</span><br><span style="color: hsl(120, 100%, 40%);">+ llist_for_each_entry(nse, &cfg->nse_peers, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (nse->nsei == nsei && !llist_empty(&nse->bts_peers))</span><br><span style="color: hsl(120, 100%, 40%);">+ return llist_first_entry(&nse->bts_peers, struct gbproxy_peer, list);</span><br><span> }</span><br><span> return NULL;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/* look-up a peer by its Routeing Area Identification (RAI) */</span><br><span style="color: hsl(120, 100%, 40%);">+/* look-up a peer by its Routeing Area Identification (RAI). There can only be one match */</span><br><span> struct gbproxy_peer *gbproxy_peer_by_rai(struct gbproxy_config *cfg,</span><br><span> const uint8_t *ra)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gbproxy_nse *nse;</span><br><span> struct gbproxy_peer *peer;</span><br><span style="color: hsl(0, 100%, 40%);">- llist_for_each_entry(peer, &cfg->bts_peers, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ gbproxy_for_each_bvc(cfg, nse, peer) {</span><br><span> if (!memcmp(peer->ra, ra, 6))</span><br><span> return peer;</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> return NULL;</span><br><span> }</span><br><span> </span><br><span> /* look-up a peer by its Location Area Identification (LAI) */</span><br><span style="color: hsl(120, 100%, 40%);">+/* FIXME: Only returns the first matching peer, but there could be multiple with the same LA */</span><br><span> struct gbproxy_peer *gbproxy_peer_by_lai(struct gbproxy_config *cfg,</span><br><span> const uint8_t *la)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gbproxy_nse *nse;</span><br><span> struct gbproxy_peer *peer;</span><br><span style="color: hsl(0, 100%, 40%);">- llist_for_each_entry(peer, &cfg->bts_peers, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+ gbproxy_for_each_bvc(cfg, nse, peer) {</span><br><span> if (!memcmp(peer->ra, la, 5))</span><br><span> return peer;</span><br><span> }</span><br><span>@@ -129,11 +138,13 @@</span><br><span> }</span><br><span> </span><br><span> /* look-up a peer by its Location Area Code (LAC) */</span><br><span style="color: hsl(120, 100%, 40%);">+/* FIXME: Only returns the first matching peer, but there could be multiple with the same LAC */</span><br><span> struct gbproxy_peer *gbproxy_peer_by_lac(struct gbproxy_config *cfg,</span><br><span> const uint8_t *la)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gbproxy_nse *nse;</span><br><span> struct gbproxy_peer *peer;</span><br><span style="color: hsl(0, 100%, 40%);">- llist_for_each_entry(peer, &cfg->bts_peers, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+ gbproxy_for_each_bvc(cfg, nse, peer) {</span><br><span> if (!memcmp(peer->ra + 3, la + 3, 2))</span><br><span> return peer;</span><br><span> }</span><br><span>@@ -172,18 +183,25 @@</span><br><span> time_t now;</span><br><span> struct timespec ts = {0,};</span><br><span> struct gbproxy_peer *peer = (struct gbproxy_peer *) data;</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(peer);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(peer->nse);</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gbproxy_config *cfg = peer->nse->cfg;</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(cfg);</span><br><span> </span><br><span> osmo_clock_gettime(CLOCK_MONOTONIC, &ts);</span><br><span> now = ts.tv_sec;</span><br><span> gbproxy_remove_stale_link_infos(peer, now);</span><br><span style="color: hsl(0, 100%, 40%);">- if (peer->cfg->clean_stale_timer_freq != 0)</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cfg->clean_stale_timer_freq != 0)</span><br><span> osmo_timer_schedule(&peer->clean_stale_timer,</span><br><span style="color: hsl(0, 100%, 40%);">- peer->cfg->clean_stale_timer_freq, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ cfg->clean_stale_timer_freq, 0);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-struct gbproxy_peer *gbproxy_peer_alloc(struct gbproxy_config *cfg, uint16_t bvci)</span><br><span style="color: hsl(120, 100%, 40%);">+struct gbproxy_peer *gbproxy_peer_alloc(struct gbproxy_nse *nse, uint16_t bvci)</span><br><span> {</span><br><span> struct gbproxy_peer *peer;</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(nse);</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gbproxy_config *cfg = nse->cfg;</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(cfg);</span><br><span> </span><br><span> peer = talloc_zero(tall_sgsn_ctx, struct gbproxy_peer);</span><br><span> if (!peer)</span><br><span>@@ -195,22 +213,24 @@</span><br><span> talloc_free(peer);</span><br><span> return NULL;</span><br><span> }</span><br><span style="color: hsl(0, 100%, 40%);">- peer->cfg = cfg;</span><br><span style="color: hsl(120, 100%, 40%);">+ peer->nse = nse;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- llist_add(&peer->list, &cfg->bts_peers);</span><br><span style="color: hsl(120, 100%, 40%);">+ llist_add(&peer->list, &nse->bts_peers);</span><br><span> </span><br><span> INIT_LLIST_HEAD(&peer->patch_state.logical_links);</span><br><span> </span><br><span> osmo_timer_setup(&peer->clean_stale_timer, clean_stale_timer_cb, peer);</span><br><span style="color: hsl(0, 100%, 40%);">- if (peer->cfg->clean_stale_timer_freq != 0)</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cfg->clean_stale_timer_freq != 0)</span><br><span> osmo_timer_schedule(&peer->clean_stale_timer,</span><br><span style="color: hsl(0, 100%, 40%);">- peer->cfg->clean_stale_timer_freq, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ cfg->clean_stale_timer_freq, 0);</span><br><span> </span><br><span> return peer;</span><br><span> }</span><br><span> </span><br><span> void gbproxy_peer_free(struct gbproxy_peer *peer)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(peer);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> llist_del(&peer->list);</span><br><span> osmo_timer_del(&peer->clean_stale_timer);</span><br><span> gbproxy_delete_link_infos(peer);</span><br><span>@@ -224,17 +244,78 @@</span><br><span> int gbproxy_cleanup_peers(struct gbproxy_config *cfg, uint16_t nsei, uint16_t bvci)</span><br><span> {</span><br><span> int counter = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- struct gbproxy_peer *peer, *tmp;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gbproxy_nse *nse, *ntmp;</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(cfg);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- llist_for_each_entry_safe(peer, tmp, &cfg->bts_peers, list) {</span><br><span style="color: hsl(0, 100%, 40%);">- if (peer->nsei != nsei)</span><br><span style="color: hsl(120, 100%, 40%);">+ llist_for_each_entry_safe(nse, ntmp, &cfg->nse_peers, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gbproxy_peer *peer, *tmp;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (nse->nsei != nsei)</span><br><span> continue;</span><br><span style="color: hsl(0, 100%, 40%);">- if (bvci && peer->bvci != bvci)</span><br><span style="color: hsl(0, 100%, 40%);">- continue;</span><br><span style="color: hsl(120, 100%, 40%);">+ llist_for_each_entry_safe(peer, tmp, &nse->bts_peers, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (bvci && peer->bvci != bvci)</span><br><span style="color: hsl(120, 100%, 40%);">+ continue;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- gbproxy_peer_free(peer);</span><br><span style="color: hsl(0, 100%, 40%);">- counter += 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ gbproxy_peer_free(peer);</span><br><span style="color: hsl(120, 100%, 40%);">+ counter += 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span> }</span><br><span> </span><br><span> return counter;</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct gbproxy_nse *gbproxy_nse_alloc(struct gbproxy_config *cfg, uint16_t nsei)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gbproxy_nse *nse;</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(cfg);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ nse = talloc_zero(tall_sgsn_ctx, struct gbproxy_nse);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!nse)</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%);">+ nse->nsei = nsei;</span><br><span style="color: hsl(120, 100%, 40%);">+ nse->cfg = cfg;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ llist_add(&nse->list, &cfg->nse_peers);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ INIT_LLIST_HEAD(&nse->bts_peers);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return nse;</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%);">+void gbproxy_nse_free(struct gbproxy_nse *nse)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gbproxy_peer *peer, *tmp;</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(nse);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ llist_del(&nse->list);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ llist_for_each_entry_safe(peer, tmp, &nse->bts_peers, list)</span><br><span style="color: hsl(120, 100%, 40%);">+ gbproxy_peer_free(peer);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ talloc_free(nse);</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%);">+struct gbproxy_nse *gbproxy_nse_by_nsei(struct gbproxy_config *cfg, uint16_t nsei)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gbproxy_nse *nse;</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(cfg);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ llist_for_each_entry(nse, &cfg->nse_peers, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (nse->nsei == nsei)</span><br><span style="color: hsl(120, 100%, 40%);">+ return nse;</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%);">+ 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%);">+struct gbproxy_nse *gbproxy_nse_by_nsei_or_new(struct gbproxy_config *cfg, uint16_t nsei)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gbproxy_nse *nse;</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(cfg);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ nse = gbproxy_nse_by_nsei(cfg, nsei);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!nse)</span><br><span style="color: hsl(120, 100%, 40%);">+ nse = gbproxy_nse_alloc(cfg, nsei);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return nse;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>\ No newline at end of file</span><br><span>diff --git a/src/gbproxy/gb_proxy_tlli.c b/src/gbproxy/gb_proxy_tlli.c</span><br><span>index e9271c2..9487459 100644</span><br><span>--- a/src/gbproxy/gb_proxy_tlli.c</span><br><span>+++ b/src/gbproxy/gb_proxy_tlli.c</span><br><span>@@ -183,12 +183,15 @@</span><br><span> int exceeded_max_len = 0;</span><br><span> int deleted_count = 0;</span><br><span> int check_for_age;</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(peer->nse);</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gbproxy_config *cfg = peer->nse->cfg;</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(cfg);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (peer->cfg->tlli_max_len > 0)</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cfg->tlli_max_len > 0)</span><br><span> exceeded_max_len =</span><br><span style="color: hsl(0, 100%, 40%);">- state->logical_link_count - peer->cfg->tlli_max_len;</span><br><span style="color: hsl(120, 100%, 40%);">+ state->logical_link_count - cfg->tlli_max_len;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- check_for_age = peer->cfg->tlli_max_age > 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ check_for_age = cfg->tlli_max_age > 0;</span><br><span> </span><br><span> for (; exceeded_max_len > 0; exceeded_max_len--) {</span><br><span> struct gbproxy_link_info *link_info;</span><br><span>@@ -213,7 +216,7 @@</span><br><span> list);</span><br><span> age = now - link_info->timestamp;</span><br><span> /* age < 0 only happens after system time jumps, discard entry */</span><br><span style="color: hsl(0, 100%, 40%);">- if (age <= peer->cfg->tlli_max_age && age >= 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (age <= cfg->tlli_max_age && age >= 0) {</span><br><span> check_for_age = 0;</span><br><span> continue;</span><br><span> }</span><br><span>@@ -395,6 +398,9 @@</span><br><span> int imsi_matches;</span><br><span> struct gbproxy_link_info *other_link_info;</span><br><span> enum gbproxy_match_id match_id;</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(peer->nse);</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gbproxy_config *cfg = peer->nse->cfg;</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(cfg);</span><br><span> </span><br><span> /* Make sure that there is a second entry with the same IMSI */</span><br><span> other_link_info = gbproxy_link_info_by_imsi(</span><br><span>@@ -419,11 +425,11 @@</span><br><span> </span><br><span> /* Check, whether the IMSI matches */</span><br><span> OSMO_ASSERT(ARRAY_SIZE(link_info->is_matching) ==</span><br><span style="color: hsl(0, 100%, 40%);">- ARRAY_SIZE(peer->cfg->matches));</span><br><span style="color: hsl(120, 100%, 40%);">+ ARRAY_SIZE(cfg->matches));</span><br><span> for (match_id = 0; match_id < ARRAY_SIZE(link_info->is_matching);</span><br><span> ++match_id) {</span><br><span> imsi_matches = gbproxy_check_imsi(</span><br><span style="color: hsl(0, 100%, 40%);">- &peer->cfg->matches[match_id],</span><br><span style="color: hsl(120, 100%, 40%);">+ &cfg->matches[match_id],</span><br><span> parse_ctx->imsi, parse_ctx->imsi_len);</span><br><span> if (imsi_matches >= 0)</span><br><span> link_info->is_matching[match_id] = imsi_matches ? true : false;</span><br><span>@@ -590,6 +596,9 @@</span><br><span> struct gprs_gb_parse_context *parse_ctx)</span><br><span> {</span><br><span> struct gbproxy_link_info *link_info = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(peer->nse);</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gbproxy_config *cfg = peer->nse->cfg;</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(cfg);</span><br><span> </span><br><span> link_info = gbproxy_get_link_info_dl(peer, parse_ctx);</span><br><span> </span><br><span>@@ -613,7 +622,7 @@</span><br><span> link_info->sgsn_tlli.ptmsi = new_sgsn_ptmsi;</span><br><span> link_info->tlli.ptmsi = new_bss_ptmsi;</span><br><span> } else if (parse_ctx->tlli_enc && parse_ctx->new_ptmsi_enc && !link_info &&</span><br><span style="color: hsl(0, 100%, 40%);">- !peer->cfg->patch_ptmsi) {</span><br><span style="color: hsl(120, 100%, 40%);">+ !cfg->patch_ptmsi) {</span><br><span> /* A new P-TMSI has been signalled in the message with an unknown</span><br><span> * TLLI, create a new link_info */</span><br><span> /* TODO: Add a test case for this branch */</span><br><span>@@ -631,7 +640,7 @@</span><br><span> link_info->tlli.ptmsi = new_ptmsi;</span><br><span> gbproxy_attach_link_info(peer, now, link_info);</span><br><span> } else if (parse_ctx->tlli_enc && parse_ctx->llc && !link_info &&</span><br><span style="color: hsl(0, 100%, 40%);">- !peer->cfg->patch_ptmsi) {</span><br><span style="color: hsl(120, 100%, 40%);">+ !cfg->patch_ptmsi) {</span><br><span> /* Unknown SGSN TLLI, create a new link_info */</span><br><span> uint32_t new_ptmsi;</span><br><span> link_info = gbproxy_link_info_alloc(peer);</span><br><span>@@ -677,12 +686,16 @@</span><br><span> struct gprs_gb_parse_context *parse_ctx)</span><br><span> {</span><br><span> int rc = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(peer->nse);</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gbproxy_config *cfg = peer->nse->cfg;</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(cfg);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> if (parse_ctx->invalidate_tlli && link_info) {</span><br><span> int keep_info =</span><br><span style="color: hsl(0, 100%, 40%);">- peer->cfg->keep_link_infos == GBPROX_KEEP_ALWAYS ||</span><br><span style="color: hsl(0, 100%, 40%);">- (peer->cfg->keep_link_infos == GBPROX_KEEP_REATTACH &&</span><br><span style="color: hsl(120, 100%, 40%);">+ cfg->keep_link_infos == GBPROX_KEEP_ALWAYS ||</span><br><span style="color: hsl(120, 100%, 40%);">+ (cfg->keep_link_infos == GBPROX_KEEP_REATTACH &&</span><br><span> parse_ctx->await_reattach) ||</span><br><span style="color: hsl(0, 100%, 40%);">- (peer->cfg->keep_link_infos == GBPROX_KEEP_IDENTIFIED &&</span><br><span style="color: hsl(120, 100%, 40%);">+ (cfg->keep_link_infos == GBPROX_KEEP_IDENTIFIED &&</span><br><span> link_info->imsi_len > 0);</span><br><span> if (keep_info) {</span><br><span> LOGP(DGPRS, LOGL_INFO, "Unregistering TLLI %08x\n",</span><br><span>diff --git a/src/gbproxy/gb_proxy_vty.c b/src/gbproxy/gb_proxy_vty.c</span><br><span>index 236d5d3..def550e 100644</span><br><span>--- a/src/gbproxy/gb_proxy_vty.c</span><br><span>+++ b/src/gbproxy/gb_proxy_vty.c</span><br><span>@@ -73,7 +73,7 @@</span><br><span> gsm48_parse_ra(&raid, peer->ra);</span><br><span> </span><br><span> vty_out(vty, "NSEI %5u, PTP-BVCI %5u, "</span><br><span style="color: hsl(0, 100%, 40%);">- "RAI %s", peer->nsei, peer->bvci, osmo_rai_name(&raid));</span><br><span style="color: hsl(120, 100%, 40%);">+ "RAI %s", peer->nse->nsei, peer->bvci, osmo_rai_name(&raid));</span><br><span> if (peer->blocked)</span><br><span> vty_out(vty, " [BVC-BLOCKED]");</span><br><span> </span><br><span>@@ -420,6 +420,7 @@</span><br><span> GBPROXY_LINK_LIST_STR GBPROXY_CLEAN_STALE_TIMER_STR</span><br><span> "Frequency at which the periodic timer is fired (in seconds)\n")</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gbproxy_nse *nse;</span><br><span> struct gbproxy_peer *peer;</span><br><span> g_cfg->clean_stale_timer_freq = (unsigned int) atoi(argv[0]);</span><br><span> </span><br><span>@@ -427,7 +428,7 @@</span><br><span> and new frequency is desired to be lower. After initial run, periodic</span><br><span> time is used. Use random() to avoid firing timers for all peers at</span><br><span> the same time */</span><br><span style="color: hsl(0, 100%, 40%);">- llist_for_each_entry(peer, &g_cfg->bts_peers, list)</span><br><span style="color: hsl(120, 100%, 40%);">+ gbproxy_for_each_bvc(g_cfg, nse, peer)</span><br><span> osmo_timer_schedule(&peer->clean_stale_timer,</span><br><span> random() % 5, random() % 1000000);</span><br><span> </span><br><span>@@ -440,10 +441,11 @@</span><br><span> NO_STR GBPROXY_LINK_LIST_STR GBPROXY_CLEAN_STALE_TIMER_STR)</span><br><span> </span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gbproxy_nse *nse;</span><br><span> struct gbproxy_peer *peer;</span><br><span> g_cfg->clean_stale_timer_freq = 0;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- llist_for_each_entry(peer, &g_cfg->bts_peers, list)</span><br><span style="color: hsl(120, 100%, 40%);">+ gbproxy_for_each_bvc(g_cfg, nse, peer)</span><br><span> osmo_timer_del(&peer->clean_stale_timer);</span><br><span> </span><br><span> return CMD_SUCCESS;</span><br><span>@@ -536,13 +538,14 @@</span><br><span> DEFUN(show_gbproxy, show_gbproxy_cmd, "show gbproxy [stats]",</span><br><span> SHOW_STR "Display information about the Gb proxy\n" "Show statistics\n")</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gbproxy_nse *nse;</span><br><span> struct gbproxy_peer *peer;</span><br><span> int show_stats = argc >= 1;</span><br><span> </span><br><span> if (show_stats)</span><br><span> vty_out_rate_ctr_group(vty, "", g_cfg->ctrg);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- llist_for_each_entry(peer, &g_cfg->bts_peers, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+ gbproxy_for_each_bvc(g_cfg, nse, peer) {</span><br><span> gbprox_vty_print_peer(vty, peer);</span><br><span> </span><br><span> if (show_stats)</span><br><span>@@ -554,6 +557,7 @@</span><br><span> DEFUN(show_gbproxy_links, show_gbproxy_links_cmd, "show gbproxy links",</span><br><span> SHOW_STR "Display information about the Gb proxy\n" "Show logical links\n")</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gbproxy_nse *nse;</span><br><span> struct gbproxy_peer *peer;</span><br><span> time_t now;</span><br><span> struct timespec ts = {0,};</span><br><span>@@ -561,7 +565,7 @@</span><br><span> osmo_clock_gettime(CLOCK_MONOTONIC, &ts);</span><br><span> now = ts.tv_sec;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- llist_for_each_entry(peer, &g_cfg->bts_peers, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+ gbproxy_for_each_bvc(g_cfg, nse, peer) {</span><br><span> struct gbproxy_link_info *link_info;</span><br><span> struct gbproxy_patch_state *state = &peer->patch_state;</span><br><span> </span><br><span>@@ -651,15 +655,17 @@</span><br><span> if (!dry_run)</span><br><span> counter = gbproxy_cleanup_peers(g_cfg, nsei, 0);</span><br><span> else {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gbproxy_nse *nse;</span><br><span> struct gbproxy_peer *peer;</span><br><span> counter = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- llist_for_each_entry(peer, &g_cfg->bts_peers, list) {</span><br><span style="color: hsl(0, 100%, 40%);">- if (peer->nsei != nsei)</span><br><span style="color: hsl(120, 100%, 40%);">+ llist_for_each_entry(nse, &g_cfg->nse_peers, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (nse->nsei != nsei)</span><br><span> continue;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- vty_out(vty, "BVC: ");</span><br><span style="color: hsl(0, 100%, 40%);">- gbprox_vty_print_peer(vty, peer);</span><br><span style="color: hsl(0, 100%, 40%);">- counter += 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ llist_for_each_entry(peer, &nse->bts_peers, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+ vty_out(vty, "BVC: ");</span><br><span style="color: hsl(120, 100%, 40%);">+ gbprox_vty_print_peer(vty, peer);</span><br><span style="color: hsl(120, 100%, 40%);">+ counter += 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span> }</span><br><span> }</span><br><span> vty_out(vty, "%sDeleted %d BVC%s",</span><br><span>diff --git a/tests/gbproxy/gbproxy_test.c b/tests/gbproxy/gbproxy_test.c</span><br><span>index 76fc000..b3d12c0 100644</span><br><span>--- a/tests/gbproxy/gbproxy_test.c</span><br><span>+++ b/tests/gbproxy/gbproxy_test.c</span><br><span>@@ -118,6 +118,7 @@</span><br><span> static int dump_peers(FILE *stream, int indent, time_t now,</span><br><span> struct gbproxy_config *cfg)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gbproxy_nse *nse;</span><br><span> struct gbproxy_peer *peer;</span><br><span> struct gprs_ra_id raid;</span><br><span> unsigned int i;</span><br><span>@@ -128,14 +129,15 @@</span><br><span> if (rc < 0)</span><br><span> return rc;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- llist_for_each_entry(peer, &cfg->bts_peers, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ gbproxy_for_each_bvc(cfg, nse, peer) {</span><br><span> struct gbproxy_link_info *link_info;</span><br><span> struct gbproxy_patch_state *state = &peer->patch_state;</span><br><span> gsm48_parse_ra(&raid, peer->ra);</span><br><span> </span><br><span> rc = fprintf(stream, "%*s NSEI %u, BVCI %u, %sblocked, RAI %s\n",</span><br><span> indent, "",</span><br><span style="color: hsl(0, 100%, 40%);">- peer->nsei, peer->bvci,</span><br><span style="color: hsl(120, 100%, 40%);">+ nse->nsei, peer->bvci,</span><br><span> peer->blocked ? "" : "not ",</span><br><span> osmo_rai_name(&raid));</span><br><span> </span><br><span>@@ -927,6 +929,7 @@</span><br><span> "NSEI 0x%04x(%d)\n\n",</span><br><span> nsei, nsei);</span><br><span> send_ns_avail(nsi, nsei);</span><br><span style="color: hsl(120, 100%, 40%);">+ send_bssgp_reset(nsi, nsei, 0);</span><br><span> }</span><br><span> </span><br><span> static void setup_bssgp(struct gprs_ns2_inst *nsi,</span><br><span>@@ -4249,7 +4252,7 @@</span><br><span> struct gbproxy_link_info *link_info;</span><br><span> int imsi_matches = -1;</span><br><span> int tlli_already_known = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- struct gbproxy_config *cfg = peer->cfg;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gbproxy_config *cfg = peer->nse->cfg;</span><br><span> </span><br><span> /* Check, whether the IMSI matches */</span><br><span> if (gprs_is_mi_imsi(imsi, imsi_len)) {</span><br><span>@@ -4298,6 +4301,7 @@</span><br><span> static void test_gbproxy_tlli_expire(void)</span><br><span> {</span><br><span> struct gbproxy_config cfg = {0};</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gbproxy_nse *nse;</span><br><span> struct gbproxy_peer *peer;</span><br><span> const char *err_msg = NULL;</span><br><span> const uint8_t imsi1[] = { GSM_MI_TYPE_IMSI, 0x23, 0x24, 0x25, 0xf6 };</span><br><span>@@ -4312,6 +4316,7 @@</span><br><span> printf("Test TLLI info expiry\n\n");</span><br><span> </span><br><span> gbproxy_init_config(&cfg);</span><br><span style="color: hsl(120, 100%, 40%);">+ nse = gbproxy_nse_by_nsei_or_new(&cfg, 0);</span><br><span> </span><br><span> if (gbproxy_set_patch_filter(&cfg.matches[GBPROX_MATCH_PATCHING],</span><br><span> filter_re, &err_msg) != 0) {</span><br><span>@@ -4327,7 +4332,7 @@</span><br><span> </span><br><span> cfg.tlli_max_len = 0;</span><br><span> cfg.tlli_max_age = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- peer = gbproxy_peer_alloc(&cfg, 20);</span><br><span style="color: hsl(120, 100%, 40%);">+ peer = gbproxy_peer_alloc(nse, 20);</span><br><span> OSMO_ASSERT(peer->patch_state.logical_link_count == 0);</span><br><span> </span><br><span> printf(" Add TLLI 1, IMSI 1\n");</span><br><span>@@ -4366,7 +4371,7 @@</span><br><span> </span><br><span> cfg.tlli_max_len = 0;</span><br><span> cfg.tlli_max_age = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- peer = gbproxy_peer_alloc(&cfg, 20);</span><br><span style="color: hsl(120, 100%, 40%);">+ peer = gbproxy_peer_alloc(nse, 20);</span><br><span> OSMO_ASSERT(peer->patch_state.logical_link_count == 0);</span><br><span> </span><br><span> printf(" Add TLLI 1, IMSI 1\n");</span><br><span>@@ -4406,7 +4411,7 @@</span><br><span> </span><br><span> cfg.tlli_max_len = 1;</span><br><span> cfg.tlli_max_age = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- peer = gbproxy_peer_alloc(&cfg, 20);</span><br><span style="color: hsl(120, 100%, 40%);">+ peer = gbproxy_peer_alloc(nse, 20);</span><br><span> OSMO_ASSERT(peer->patch_state.logical_link_count == 0);</span><br><span> </span><br><span> printf(" Add TLLI 1, IMSI 1\n");</span><br><span>@@ -4444,7 +4449,7 @@</span><br><span> </span><br><span> cfg.tlli_max_len = 0;</span><br><span> cfg.tlli_max_age = 1;</span><br><span style="color: hsl(0, 100%, 40%);">- peer = gbproxy_peer_alloc(&cfg, 20);</span><br><span style="color: hsl(120, 100%, 40%);">+ peer = gbproxy_peer_alloc(nse, 20);</span><br><span> OSMO_ASSERT(peer->patch_state.logical_link_count == 0);</span><br><span> </span><br><span> printf(" Add TLLI 1, IMSI 1 (should expire after timeout)\n");</span><br><span>@@ -4482,7 +4487,7 @@</span><br><span> </span><br><span> cfg.tlli_max_len = 0;</span><br><span> cfg.tlli_max_age = 1;</span><br><span style="color: hsl(0, 100%, 40%);">- peer = gbproxy_peer_alloc(&cfg, 20);</span><br><span style="color: hsl(120, 100%, 40%);">+ peer = gbproxy_peer_alloc(nse, 20);</span><br><span> OSMO_ASSERT(peer->patch_state.logical_link_count == 0);</span><br><span> </span><br><span> printf(" Add TLLI 1, IMSI 1 (should expire)\n");</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-sgsn/+/21406">change 21406</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-sgsn/+/21406"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: osmo-sgsn </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I97cc6c8f8c0f1b91577ab8f679c4ae217cc88076 </div>
<div style="display:none"> Gerrit-Change-Number: 21406 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: daniel <dwillmann@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>