<p>laforge <strong>submitted</strong> this change.</p><p><a href="https://gerrit.osmocom.org/c/osmo-sgsn/+/21550">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Jenkins Builder: Verified
  pespin: Looks good to me, but someone else must approve
  laforge: Looks good to me, approved

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">gbproxy: convert bss_nses from llist_head to hashtable<br><br>For the common lookup-by-nsei, this should reduce the computational<br>complexity significantly.<br><br>Depends: libosmocore.git I8ef73a62fe9846ce45058eb21cf999dd3eed5741<br>Change-Id: Idbb6a362332bb6e3ce22102e7409ae80d0980f44<br>---<br>M TODO-RELEASE<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_peer.c<br>M src/gbproxy/gb_proxy_vty.c<br>M tests/gbproxy/gbproxy_test.c<br>7 files changed, 56 insertions(+), 35 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/TODO-RELEASE b/TODO-RELEASE</span><br><span>index 6b29a87..1e409b5 100644</span><br><span>--- a/TODO-RELEASE</span><br><span>+++ b/TODO-RELEASE</span><br><span>@@ -1,2 +1,3 @@</span><br><span> #component    what            description / commit summary line</span><br><span> manual                             needs common chapter cs7-config.adoc, vty_cpu_sched.adoc from osmo-gsm-manuals > 0.3.0</span><br><span style="color: hsl(120, 100%, 40%);">+configure.ac libosmocore     depend on next released libosmocore after 1.4.x with hashtable support</span><br><span>diff --git a/include/osmocom/sgsn/gb_proxy.h b/include/osmocom/sgsn/gb_proxy.h</span><br><span>index 27b47cf..b0ab83d 100644</span><br><span>--- a/include/osmocom/sgsn/gb_proxy.h</span><br><span>+++ b/include/osmocom/sgsn/gb_proxy.h</span><br><span>@@ -4,6 +4,7 @@</span><br><span> </span><br><span> #include <osmocom/core/msgb.h></span><br><span> #include <osmocom/core/timer.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/hashtable.h></span><br><span> #include <osmocom/gsm/gsm23003.h></span><br><span> </span><br><span> #include <osmocom/gprs/gprs_ns2.h></span><br><span>@@ -102,7 +103,7 @@</span><br><span>   struct gprs_ns2_inst *nsi;</span><br><span> </span><br><span>       /* Linked list of all BSS side Gb peers */</span><br><span style="color: hsl(0, 100%, 40%);">-      struct llist_head bss_nses;</span><br><span style="color: hsl(120, 100%, 40%);">+   DECLARE_HASHTABLE(bss_nses, 8);</span><br><span> </span><br><span>  /* Counter */</span><br><span>        struct rate_ctr_group *ctrg;</span><br><span>@@ -176,7 +177,7 @@</span><br><span> /* one NS Entity that we interact with (BSS/PCU) */</span><br><span> struct gbproxy_nse {</span><br><span>    /* linked to gbproxy_config.bss_nses */</span><br><span style="color: hsl(0, 100%, 40%);">- struct llist_head list;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct hlist_node list;</span><br><span> </span><br><span>  /* point back to the config */</span><br><span>       struct gbproxy_config *cfg;</span><br><span>diff --git a/src/gbproxy/gb_proxy.c b/src/gbproxy/gb_proxy.c</span><br><span>index 4c34941..c37b21a 100644</span><br><span>--- a/src/gbproxy/gb_proxy.c</span><br><span>+++ b/src/gbproxy/gb_proxy.c</span><br><span>@@ -31,6 +31,7 @@</span><br><span> #include <arpa/inet.h></span><br><span> #include <time.h></span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/hashtable.h></span><br><span> #include <osmocom/core/logging.h></span><br><span> #include <osmocom/core/talloc.h></span><br><span> #include <osmocom/core/select.h></span><br><span>@@ -1183,6 +1184,7 @@</span><br><span>        struct gbproxy_bvc *bvc;</span><br><span>     unsigned int n_nses = 0;</span><br><span>     int errctr = GBPROX_GLOB_CTR_PROTO_ERR_SGSN;</span><br><span style="color: hsl(120, 100%, 40%);">+  int i;</span><br><span> </span><br><span>   /* FIXME: Handle paging logic to only page each matching NSE */</span><br><span> </span><br><span>@@ -1203,7 +1205,7 @@</span><br><span>  } else if (TLVP_PRES_LEN(tp, BSSGP_IE_ROUTEING_AREA, 6)) {</span><br><span>           errctr = GBPROX_GLOB_CTR_INV_RAI;</span><br><span>            /* iterate over all bvcs and dispatch the paging to each matching one */</span><br><span style="color: hsl(0, 100%, 40%);">-                llist_for_each_entry(nse, &cfg->bss_nses, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+              hash_for_each(cfg->bss_nses, i, nse, list) {</span><br><span>                      llist_for_each_entry(bvc, &nse->bvcs, list) {</span><br><span>                                 if (!memcmp(bvc->ra, TLVP_VAL(tp, BSSGP_IE_ROUTEING_AREA), 6)) {</span><br><span>                                  LOGPNSE(nse, LOGL_INFO, "routing to NSE (RAI match)\n");</span><br><span>@@ -1217,7 +1219,7 @@</span><br><span>   } else if (TLVP_PRES_LEN(tp, BSSGP_IE_LOCATION_AREA, 5)) {</span><br><span>           errctr = GBPROX_GLOB_CTR_INV_LAI;</span><br><span>            /* iterate over all bvcs and dispatch the paging to each matching one */</span><br><span style="color: hsl(0, 100%, 40%);">-                llist_for_each_entry(nse, &cfg->bss_nses, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+              hash_for_each(cfg->bss_nses, i, nse, list) {</span><br><span>                      llist_for_each_entry(bvc, &nse->bvcs, list) {</span><br><span>                                 if (!memcmp(bvc->ra, TLVP_VAL(tp, BSSGP_IE_LOCATION_AREA), 5)) {</span><br><span>                                  LOGPNSE(nse, LOGL_INFO, "routing to NSE (LAI match)\n");</span><br><span>@@ -1230,7 +1232,7 @@</span><br><span>           }</span><br><span>    } else if (TLVP_PRES_LEN(tp, BSSGP_IE_BSS_AREA_ID, 1)) {</span><br><span>             /* iterate over all bvcs and dispatch the paging to each matching one */</span><br><span style="color: hsl(0, 100%, 40%);">-                llist_for_each_entry(nse, &cfg->bss_nses, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+              hash_for_each(cfg->bss_nses, i, nse, list) {</span><br><span>                      llist_for_each_entry(bvc, &nse->bvcs, list) {</span><br><span>                                 LOGPNSE(nse, LOGL_INFO, "routing to NSE (broadcast)\n");</span><br><span>                           gbprox_relay2nse(msg, nse, ns_bvci);</span><br><span>@@ -1263,6 +1265,7 @@</span><br><span>         struct gbproxy_nse *nse;</span><br><span>     struct gbproxy_bvc *bvc;</span><br><span>     uint16_t ptp_bvci;</span><br><span style="color: hsl(120, 100%, 40%);">+    int i;</span><br><span> </span><br><span>   if (!TLVP_PRES_LEN(tp, BSSGP_IE_BVCI, 2)) {</span><br><span>          rate_ctr_inc(&cfg->ctrg-></span><br><span>@@ -1291,7 +1294,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(nse, &cfg->bss_nses, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+      hash_for_each(cfg->bss_nses, i, nse, list) {</span><br><span>              llist_for_each_entry(bvc, &nse->bvcs, list)</span><br><span>                   gbprox_relay2peer(msg, bvc, ns_bvci);</span><br><span>        }</span><br><span>@@ -1315,6 +1318,7 @@</span><br><span>    struct msgb *msg;</span><br><span>    int rc = 0;</span><br><span>  int cause;</span><br><span style="color: hsl(120, 100%, 40%);">+    int i;</span><br><span> </span><br><span>   if (ns_bvci != 0 && ns_bvci != 1) {</span><br><span>          LOGP(DGPRS, LOGL_NOTICE, "NSE(%05u/SGSN) BVCI=%05u is not "</span><br><span>@@ -1425,7 +1429,7 @@</span><br><span>                LOGP(DGPRS, LOGL_DEBUG,</span><br><span>                      "NSE(%05u/SGSN) BSSGP %s: broadcasting\n", nsei, bssgp_pdu_str(pdu_type));</span><br><span>                 /* broadcast to all BSS-side bvcs */</span><br><span style="color: hsl(0, 100%, 40%);">-            llist_for_each_entry(nse, &cfg->bss_nses, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+              hash_for_each(cfg->bss_nses, i, nse, list) {</span><br><span>                      gbprox_relay2nse(msg, nse, 0);</span><br><span>               }</span><br><span>            break;</span><br><span>@@ -1618,9 +1622,11 @@</span><br><span> </span><br><span> void gbprox_reset(struct gbproxy_config *cfg)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-       struct gbproxy_nse *nse, *ntmp;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct gbproxy_nse *nse;</span><br><span style="color: hsl(120, 100%, 40%);">+      struct hlist_node *ntmp;</span><br><span style="color: hsl(120, 100%, 40%);">+      int i;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-      llist_for_each_entry_safe(nse, ntmp, &cfg->bss_nses, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+   hash_for_each_safe(cfg->bss_nses, i, ntmp, nse, list) {</span><br><span>           struct gbproxy_bvc *bvc, *tmp;</span><br><span>               llist_for_each_entry_safe(bvc, tmp, &nse->bvcs, list)</span><br><span>                         gbproxy_bvc_free(bvc);</span><br><span>@@ -1636,7 +1642,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->bss_nses);</span><br><span style="color: hsl(120, 100%, 40%);">+       hash_init(cfg->bss_nses);</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 c3cfddf..8290412 100644</span><br><span>--- a/src/gbproxy/gb_proxy_ctrl.c</span><br><span>+++ b/src/gbproxy/gb_proxy_ctrl.c</span><br><span>@@ -56,6 +56,7 @@</span><br><span>   struct gprs_ns2_inst *nsi = cfg->nsi;</span><br><span>     struct gprs_ns2_nse *nse;</span><br><span>    struct gbproxy_nse *nse_peer;</span><br><span style="color: hsl(120, 100%, 40%);">+ int i;</span><br><span> </span><br><span>   cmd->reply = talloc_strdup(cmd, "");</span><br><span> </span><br><span>@@ -69,7 +70,7 @@</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(nse_peer, &cfg->bss_nses, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+ hash_for_each(cfg->bss_nses, i, nse_peer, list) {</span><br><span>                 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>@@ -84,10 +85,11 @@</span><br><span> {</span><br><span>     struct gbproxy_config *cfg = data;</span><br><span>   struct gbproxy_nse *nse_peer;</span><br><span style="color: hsl(120, 100%, 40%);">+ int i;</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(nse_peer, &cfg->bss_nses, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+ hash_for_each(cfg->bss_nses, i, nse_peer, list) {</span><br><span>                 struct gbproxy_bvc *bvc;</span><br><span>             llist_for_each_entry(bvc, &nse_peer->bvcs, list) {</span><br><span>                    struct gprs_ra_id raid;</span><br><span>@@ -111,8 +113,9 @@</span><br><span>        struct gbproxy_config *cfg = data;</span><br><span>   struct gbproxy_nse *nse_peer;</span><br><span>        uint32_t count = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+   int i;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-      llist_for_each_entry(nse_peer, &cfg->bss_nses, list)</span><br><span style="color: hsl(120, 100%, 40%);">+   hash_for_each(cfg->bss_nses, i, nse_peer, list)</span><br><span>           count += llist_count(&nse_peer->bvcs);</span><br><span> </span><br><span>    cmd->reply = talloc_strdup(cmd, "");</span><br><span>diff --git a/src/gbproxy/gb_proxy_peer.c b/src/gbproxy/gb_proxy_peer.c</span><br><span>index c48a78f..00bff20 100644</span><br><span>--- a/src/gbproxy/gb_proxy_peer.c</span><br><span>+++ b/src/gbproxy/gb_proxy_peer.c</span><br><span>@@ -86,8 +86,9 @@</span><br><span> struct gbproxy_bvc *gbproxy_bvc_by_bvci(struct gbproxy_config *cfg, uint16_t bvci)</span><br><span> {</span><br><span>    struct gbproxy_nse *nse;</span><br><span style="color: hsl(120, 100%, 40%);">+      int i;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-      llist_for_each_entry(nse, &cfg->bss_nses, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+      hash_for_each(cfg->bss_nses, i, nse, list) {</span><br><span>              struct gbproxy_bvc *bvc;</span><br><span>             llist_for_each_entry(bvc, &nse->bvcs, list) {</span><br><span>                         if (bvc->bvci == bvci)</span><br><span>@@ -102,11 +103,11 @@</span><br><span> struct gbproxy_bvc *gbproxy_bvc_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_nse *nse;</span><br><span style="color: hsl(0, 100%, 40%);">-        llist_for_each_entry(nse, &cfg->bss_nses, list) {</span><br><span style="color: hsl(0, 100%, 40%);">-                if (nse->nsei == nsei && !llist_empty(&nse->bvcs))</span><br><span style="color: hsl(0, 100%, 40%);">-                    return llist_first_entry(&nse->bvcs, struct gbproxy_bvc, list);</span><br><span style="color: hsl(0, 100%, 40%);">-  }</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (nse && !llist_empty(&nse->bvcs))</span><br><span style="color: hsl(120, 100%, 40%);">+           return llist_first_entry(&nse->bvcs, struct gbproxy_bvc, list);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>     return NULL;</span><br><span> }</span><br><span> </span><br><span>@@ -116,8 +117,9 @@</span><br><span>                                   const uint8_t *ra)</span><br><span> {</span><br><span>     struct gbproxy_nse *nse;</span><br><span style="color: hsl(120, 100%, 40%);">+      int i;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-      llist_for_each_entry(nse, &cfg->bss_nses, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+      hash_for_each(cfg->bss_nses, i, nse, list) {</span><br><span>              struct gbproxy_bvc *bvc;</span><br><span>             llist_for_each_entry(bvc, &nse->bvcs, list) {</span><br><span>                         if (!memcmp(bvc->ra, ra, 6))</span><br><span>@@ -134,8 +136,9 @@</span><br><span>                                         const uint8_t *la)</span><br><span> {</span><br><span>     struct gbproxy_nse *nse;</span><br><span style="color: hsl(120, 100%, 40%);">+      int i;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-      llist_for_each_entry(nse, &cfg->bss_nses, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+      hash_for_each(cfg->bss_nses, i, nse, list) {</span><br><span>              struct gbproxy_bvc *bvc;</span><br><span>             llist_for_each_entry(bvc, &nse->bvcs, list) {</span><br><span>                         if (!memcmp(bvc->ra, la, 5))</span><br><span>@@ -151,8 +154,9 @@</span><br><span>                                         const uint8_t *la)</span><br><span> {</span><br><span>     struct gbproxy_nse *nse;</span><br><span style="color: hsl(120, 100%, 40%);">+      int i;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-      llist_for_each_entry(nse, &cfg->bss_nses, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+      hash_for_each(cfg->bss_nses, i, nse, list) {</span><br><span>              struct gbproxy_bvc *bvc;</span><br><span>             llist_for_each_entry(bvc, &nse->bvcs, list) {</span><br><span>                         if (!memcmp(bvc->ra + 3, la + 3, 2))</span><br><span>@@ -268,11 +272,12 @@</span><br><span>  *  \param[in] bvci if 0: remove all BVCs; if != 0: BVCI of the single BVC to clean up */</span><br><span> int gbproxy_cleanup_bvcs(struct gbproxy_config *cfg, uint16_t nsei, uint16_t bvci)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- int counter = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-        struct gbproxy_nse *nse, *ntmp;</span><br><span style="color: hsl(120, 100%, 40%);">+       int i, counter = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+   struct gbproxy_nse *nse;</span><br><span style="color: hsl(120, 100%, 40%);">+      struct hlist_node *ntmp;</span><br><span>     OSMO_ASSERT(cfg);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   llist_for_each_entry_safe(nse, ntmp, &cfg->bss_nses, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+   hash_for_each_safe(cfg->bss_nses, i, ntmp, nse, list) {</span><br><span>           struct gbproxy_bvc *bvc, *tmp;</span><br><span>               if (nse->nsei != nsei)</span><br><span>                    continue;</span><br><span>@@ -300,7 +305,7 @@</span><br><span>      nse->nsei = nsei;</span><br><span>         nse->cfg = cfg;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-  llist_add(&nse->list, &cfg->bss_nses);</span><br><span style="color: hsl(120, 100%, 40%);">+  hash_add(cfg->bss_nses, &nse->list, nsei);</span><br><span> </span><br><span>     INIT_LLIST_HEAD(&nse->bvcs);</span><br><span> </span><br><span>@@ -313,7 +318,7 @@</span><br><span>        if (!nse)</span><br><span>            return;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     llist_del(&nse->list);</span><br><span style="color: hsl(120, 100%, 40%);">+ hash_del(&nse->list);</span><br><span> </span><br><span>     llist_for_each_entry_safe(bvc, tmp, &nse->bvcs, list)</span><br><span>                 gbproxy_bvc_free(bvc);</span><br><span>@@ -326,7 +331,7 @@</span><br><span>         struct gbproxy_nse *nse;</span><br><span>     OSMO_ASSERT(cfg);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   llist_for_each_entry(nse, &cfg->bss_nses, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+      hash_for_each_possible(cfg->bss_nses, nse, list, nsei) {</span><br><span>          if (nse->nsei == nsei)</span><br><span>                    return nse;</span><br><span>  }</span><br><span>diff --git a/src/gbproxy/gb_proxy_vty.c b/src/gbproxy/gb_proxy_vty.c</span><br><span>index e79297d..da8afdc 100644</span><br><span>--- a/src/gbproxy/gb_proxy_vty.c</span><br><span>+++ b/src/gbproxy/gb_proxy_vty.c</span><br><span>@@ -422,13 +422,14 @@</span><br><span>       "Frequency at which the periodic timer is fired (in seconds)\n")</span><br><span> {</span><br><span>      struct gbproxy_nse *nse;</span><br><span style="color: hsl(120, 100%, 40%);">+      int i;</span><br><span>       g_cfg->clean_stale_timer_freq = (unsigned int) atoi(argv[0]);</span><br><span> </span><br><span>         /* Re-schedule running timers soon in case prev frequency was really big</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 bvcs at</span><br><span>            the same time */</span><br><span style="color: hsl(0, 100%, 40%);">-     llist_for_each_entry(nse, &g_cfg->bss_nses, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+    hash_for_each(g_cfg->bss_nses, i, nse, list) {</span><br><span>            struct gbproxy_bvc *bvc;</span><br><span>             llist_for_each_entry(bvc, &nse->bvcs, list)</span><br><span>                   osmo_timer_schedule(&bvc->clean_stale_timer,</span><br><span>@@ -445,9 +446,10 @@</span><br><span> </span><br><span> {</span><br><span>  struct gbproxy_nse *nse;</span><br><span style="color: hsl(120, 100%, 40%);">+      int i;</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(nse, &g_cfg->bss_nses, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+    hash_for_each(g_cfg->bss_nses, i, nse, list) {</span><br><span>            struct gbproxy_bvc *bvc;</span><br><span>             llist_for_each_entry(bvc, &nse->bvcs, list)</span><br><span>                   osmo_timer_del(&bvc->clean_stale_timer);</span><br><span>@@ -580,11 +582,12 @@</span><br><span> {</span><br><span>         struct gbproxy_nse *nse;</span><br><span>     int show_stats = argc >= 1;</span><br><span style="color: hsl(120, 100%, 40%);">+        int i;</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(nse, &g_cfg->bss_nses, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+    hash_for_each(g_cfg->bss_nses, i, nse, list) {</span><br><span>            struct gbproxy_bvc *bvc;</span><br><span>             llist_for_each_entry(bvc, &nse->bvcs, list) {</span><br><span>                         gbprox_vty_print_bvc(vty, bvc);</span><br><span>@@ -602,11 +605,12 @@</span><br><span>      struct gbproxy_nse *nse;</span><br><span>     time_t now;</span><br><span>  struct timespec ts = {0,};</span><br><span style="color: hsl(120, 100%, 40%);">+    int i;</span><br><span> </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(nse, &g_cfg->bss_nses, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+    hash_for_each(g_cfg->bss_nses, i, nse, list) {</span><br><span>            struct gbproxy_bvc *bvc;</span><br><span>             llist_for_each_entry(bvc, &nse->bvcs, list) {</span><br><span>                         struct gbproxy_link_info *link_info;</span><br><span>@@ -703,8 +707,9 @@</span><br><span>           } else {</span><br><span>                     struct gbproxy_nse *nse;</span><br><span>                     struct gbproxy_bvc *bvc;</span><br><span style="color: hsl(120, 100%, 40%);">+                      int i;</span><br><span>                       counter = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-                    llist_for_each_entry(nse, &g_cfg->bss_nses, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+                    hash_for_each(g_cfg->bss_nses, i, nse, list) {</span><br><span>                            if (nse->nsei != nsei)</span><br><span>                                    continue;</span><br><span>                            llist_for_each_entry(bvc, &nse->bvcs, list) {</span><br><span>diff --git a/tests/gbproxy/gbproxy_test.c b/tests/gbproxy/gbproxy_test.c</span><br><span>index 5538089..bd5c8b5 100644</span><br><span>--- a/tests/gbproxy/gbproxy_test.c</span><br><span>+++ b/tests/gbproxy/gbproxy_test.c</span><br><span>@@ -120,7 +120,7 @@</span><br><span> {</span><br><span>         struct gbproxy_nse *nse;</span><br><span>     struct gprs_ra_id raid;</span><br><span style="color: hsl(0, 100%, 40%);">- unsigned int i;</span><br><span style="color: hsl(120, 100%, 40%);">+       unsigned int i, _nse;</span><br><span>        const struct rate_ctr_group_desc *desc;</span><br><span>      int rc;</span><br><span> </span><br><span>@@ -129,7 +129,7 @@</span><br><span>            return rc;</span><br><span> </span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-      llist_for_each_entry(nse, &cfg->bss_nses, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+      hash_for_each(cfg->bss_nses, _nse, nse, list) {</span><br><span>           struct gbproxy_bvc *peer;</span><br><span>            llist_for_each_entry(peer, &nse->bvcs, list) {</span><br><span>                        struct gbproxy_link_info *link_info;</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-sgsn/+/21550">change 21550</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/+/21550"/><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: Idbb6a362332bb6e3ce22102e7409ae80d0980f44 </div>
<div style="display:none"> Gerrit-Change-Number: 21550 </div>
<div style="display:none"> Gerrit-PatchSet: 2 </div>
<div style="display:none"> Gerrit-Owner: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>
<div style="display:none"> Gerrit-Reviewer: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-Reviewer: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>