<p>daniel has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/osmo-sgsn/+/21960">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">WIP gbproxy: Implment TLLI cache and use it for SUSPEND/RESUME<br><br>Deleting cache entries by timer or reception of NACK/ACK is missing<br><br>Related: SYS#4865, OS#4472<br>Change-Id: I42adf70f560d2bb358a9e1c7614281e8d2967568<br>---<br>M include/osmocom/sgsn/gb_proxy.h<br>M src/gbproxy/gb_proxy.c<br>M src/gbproxy/gb_proxy_peer.c<br>3 files changed, 90 insertions(+), 0 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/60/21960/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 ad5bb27..ea9e649 100644</span><br><span>--- a/include/osmocom/sgsn/gb_proxy.h</span><br><span>+++ b/include/osmocom/sgsn/gb_proxy.h</span><br><span>@@ -75,6 +75,9 @@</span><br><span>       /* hash table of all gbproxy_cell */</span><br><span>         DECLARE_HASHTABLE(cells, 8);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+      /* tlli<->sgsn cache */</span><br><span style="color: hsl(120, 100%, 40%);">+ DECLARE_HASHTABLE(tlli_cache, 10);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>         /* List of all SGSNs */</span><br><span>      struct llist_head sgsns;</span><br><span> </span><br><span>@@ -163,6 +166,19 @@</span><br><span>  } pool;</span><br><span> };</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/* TLLI cache */</span><br><span style="color: hsl(120, 100%, 40%);">+struct gbproxy_tlli_cache {</span><br><span style="color: hsl(120, 100%, 40%);">+      /* linked to gbproxy_config.tlli_cache */</span><br><span style="color: hsl(120, 100%, 40%);">+     struct hlist_node list;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /* TLLI of the entry */</span><br><span style="color: hsl(120, 100%, 40%);">+       uint32_t tlli;</span><br><span style="color: hsl(120, 100%, 40%);">+        /* When was this entry last seen */</span><br><span style="color: hsl(120, 100%, 40%);">+   struct timespec tstamp;</span><br><span style="color: hsl(120, 100%, 40%);">+       /* The Cell this TLLI was last seen */</span><br><span style="color: hsl(120, 100%, 40%);">+        struct gbproxy_nse *nse;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* Convenience logging macros for NSE/BVC */</span><br><span> #define LOGPNSE_CAT(NSE, SUBSYS, LEVEL, FMT, ARGS...) \</span><br><span>    LOGP(SUBSYS, LEVEL, "NSE(%05u/%s) " FMT, (NSE)->nsei, \</span><br><span>@@ -229,6 +245,8 @@</span><br><span> void gbproxy_nse_free(struct gbproxy_nse *nse);</span><br><span> struct gbproxy_nse *gbproxy_nse_by_nsei(struct gbproxy_config *cfg, uint16_t nsei, uint32_t flags);</span><br><span> struct gbproxy_nse *gbproxy_nse_by_nsei_or_new(struct gbproxy_config *cfg, uint16_t nsei, bool sgsn_facing);</span><br><span style="color: hsl(120, 100%, 40%);">+void gbproxy_nse_cache_tlli(struct gbproxy_nse *nse, uint32_t tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+struct gbproxy_nse *gbproxy_nse_by_tlli(struct gbproxy_config *cfg, uint32_t tlli);</span><br><span> </span><br><span> /* SGSN handling */</span><br><span> struct gbproxy_sgsn *gbproxy_sgsn_alloc(struct gbproxy_config *cfg, uint16_t nsei, const char *name);</span><br><span>diff --git a/src/gbproxy/gb_proxy.c b/src/gbproxy/gb_proxy.c</span><br><span>index 34cff31..a260ec9 100644</span><br><span>--- a/src/gbproxy/gb_proxy.c</span><br><span>+++ b/src/gbproxy/gb_proxy.c</span><br><span>@@ -890,11 +890,26 @@</span><br><span>             return osmo_fsm_inst_dispatch(from_bvc->fi, BSSGP_BVCFSM_E_RX_UNBLOCK, msg);</span><br><span>      case BSSGP_PDUT_SUSPEND:</span><br><span>     case BSSGP_PDUT_RESUME:</span><br><span style="color: hsl(120, 100%, 40%);">+       {</span><br><span style="color: hsl(120, 100%, 40%);">+             struct gbproxy_sgsn *sgsn;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>                 /* FIXME: Implement TLLI Cache.  Every SUSPEND/RESUME we must</span><br><span>                 * take record of the TLLI->BVC mapping so we can map</span><br><span>              * back from TLLI->BVC when the SUSPEND/RESUME-ACK</span><br><span>                 * arrives.  Cache should have a timeout of 1-3 seconds</span><br><span>               * and the ACK should explicitly delete entries. */</span><br><span style="color: hsl(120, 100%, 40%);">+           tlli = osmo_load32be(TLVP_VAL(&tp, BSSGP_IE_TLLI));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+             sgsn = gbproxy_select_sgsn(nse->cfg, &tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+           if (!sgsn) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  LOGP(DGPRS, LOGL_ERROR, "Could not find any SGSN for TLLI, dropping message!\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                   rc = -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+                 break;</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%);">+           gbproxy_nse_cache_tlli(nse, tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+          rc = gbprox_relay2nse(msg, sgsn->nse, 0);</span><br><span> #if 0</span><br><span>                /* TODO: Validate the RAI for consistency with the RAI</span><br><span>                * we expect for any of the BVC within this BSS side NSE */</span><br><span>@@ -902,6 +917,7 @@</span><br><span>            gsm48_parse_ra(&raid, from_bvc->ra);</span><br><span> #endif</span><br><span>                break;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span>    case BSSGP_PDUT_STATUS:</span><br><span>              /* FIXME: inspect the erroneous PDU IE (if any) and check</span><br><span>             * if we can extract a TLLI/RNI to route it to the correct SGSN */</span><br><span>@@ -1149,11 +1165,26 @@</span><br><span>         case BSSGP_PDUT_SUSPEND_NACK:</span><br><span>        case BSSGP_PDUT_RESUME_ACK:</span><br><span>  case BSSGP_PDUT_RESUME_NACK:</span><br><span style="color: hsl(120, 100%, 40%);">+  {</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 tlli = osmo_load32be(TLVP_VAL(&tp, BSSGP_IE_TLLI));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>           /* FIXME: handle based on TLLI cache. The RA-ID is not a unique</span><br><span>               * criterion, so we have to rely on the TLLI->BVC state created</span><br><span>            * while processing the SUSPEND/RESUME in uplink */</span><br><span>          /* FIXME: route to SGSN baed on NRI derived from TLLI */</span><br><span style="color: hsl(120, 100%, 40%);">+              nse_peer = gbproxy_nse_by_tlli(cfg, tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+            if (!nse_peer) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      LOGPNSE(nse, LOGL_ERROR, "Rx %s: Cannot find NSE\n", pdut_name);</span><br><span style="color: hsl(120, 100%, 40%);">+                    //rate_ctr_inc(&cfg->ctrg-> ctr[GBPROX_GLOB_CTR_INV_RAI]);</span><br><span style="color: hsl(120, 100%, 40%);">+                  // FIXME</span><br><span style="color: hsl(120, 100%, 40%);">+                      return bssgp_tx_status(BSSGP_CAUSE_INV_MAND_INF, NULL, msg);</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%);">+           LOGPNSE(nse_peer, LOGL_DEBUG, "Rx %s: forwarding\n", pdut_name);</span><br><span style="color: hsl(120, 100%, 40%);">+            gbprox_relay2nse(msg, nse_peer, ns_bvci);</span><br><span>            break;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span>    case BSSGP_PDUT_SGSN_INVOKE_TRACE:</span><br><span>   case BSSGP_PDUT_OVERLOAD:</span><br><span>            LOGPNSE(nse, LOGL_DEBUG, "Rx %s: broadcasting\n", pdut_name);</span><br><span>@@ -1386,6 +1417,7 @@</span><br><span>      hash_init(cfg->bss_nses);</span><br><span>         hash_init(cfg->sgsn_nses);</span><br><span>        hash_init(cfg->cells);</span><br><span style="color: hsl(120, 100%, 40%);">+     hash_init(cfg->tlli_cache);</span><br><span>       INIT_LLIST_HEAD(&cfg->sgsns);</span><br><span> </span><br><span>     cfg->ctrg = rate_ctr_group_alloc(tall_sgsn_ctx, &global_ctrg_desc, 0);</span><br><span>diff --git a/src/gbproxy/gb_proxy_peer.c b/src/gbproxy/gb_proxy_peer.c</span><br><span>index 7c00fc7..95ec68a 100644</span><br><span>--- a/src/gbproxy/gb_proxy_peer.c</span><br><span>+++ b/src/gbproxy/gb_proxy_peer.c</span><br><span>@@ -192,6 +192,46 @@</span><br><span>        return NULL;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static inline struct gbproxy_tlli_cache *_get_tlli_entry(struct gbproxy_config *cfg, uint32_t tlli)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gbproxy_tlli_cache *cache_entry;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     hash_for_each_possible(cfg->tlli_cache, cache_entry, list, tlli) {</span><br><span style="color: hsl(120, 100%, 40%);">+         if (cache_entry->tlli == tlli)</span><br><span style="color: hsl(120, 100%, 40%);">+                     return cache_entry;</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%);">+void gbproxy_nse_cache_tlli(struct gbproxy_nse *nse, uint32_t tlli)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     struct gbproxy_config *cfg = nse->cfg;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct gbproxy_tlli_cache *cache_entry = _get_tlli_entry(cfg, tlli);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if (cache_entry) {</span><br><span style="color: hsl(120, 100%, 40%);">+            // Update the entry if it already exists</span><br><span style="color: hsl(120, 100%, 40%);">+              cache_entry->nse = nse;</span><br><span style="color: hsl(120, 100%, 40%);">+            osmo_clock_gettime(CLOCK_MONOTONIC, &cache_entry->tstamp);</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%);">+   cache_entry = talloc_zero(cfg, struct gbproxy_tlli_cache);</span><br><span style="color: hsl(120, 100%, 40%);">+    cache_entry->tlli = tlli;</span><br><span style="color: hsl(120, 100%, 40%);">+  cache_entry->nse = nse;</span><br><span style="color: hsl(120, 100%, 40%);">+    osmo_clock_gettime(CLOCK_MONOTONIC, &cache_entry->tstamp);</span><br><span style="color: hsl(120, 100%, 40%);">+     hash_add(cfg->tlli_cache, &cache_entry->list, cache_entry->tlli);</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_tlli(struct gbproxy_config *cfg, uint32_t tlli)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    struct gbproxy_tlli_cache *tlli_cache;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      hash_for_each_possible(cfg->tlli_cache, tlli_cache, list, tlli) {</span><br><span style="color: hsl(120, 100%, 40%);">+          if (tlli_cache->tlli == tlli)</span><br><span style="color: hsl(120, 100%, 40%);">+                      return tlli_cache->nse;</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> struct gbproxy_cell *gbproxy_cell_by_bvci_or_new(struct gbproxy_config *cfg, uint16_t bvci)</span><br><span> {</span><br><span>        struct gbproxy_cell *cell;</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-sgsn/+/21960">change 21960</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/+/21960"/><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: I42adf70f560d2bb358a9e1c7614281e8d2967568 </div>
<div style="display:none"> Gerrit-Change-Number: 21960 </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>