<p>lynxis lazus has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/libosmocore/+/24923">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">WIP: gprs_ns2: start use (ref) counting<br><br>Also avoid recursive free() rounds within the ns2 code<br><br>Change-Id: I03cb2419926c639d4bd357a33ce8008c50cd3bee<br>---<br>M src/gb/gprs_ns2.c<br>M src/gb/gprs_ns2_internal.h<br>M src/gb/gprs_ns2_sns.c<br>M tests/gb/gprs_ns2_test.c<br>M tests/gb/gprs_ns2_test.ok<br>5 files changed, 137 insertions(+), 17 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/23/24923/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/gb/gprs_ns2.c b/src/gb/gprs_ns2.c</span><br><span>index 3eb59e5..09286ec 100644</span><br><span>--- a/src/gb/gprs_ns2.c</span><br><span>+++ b/src/gb/gprs_ns2.c</span><br><span>@@ -236,6 +236,8 @@</span><br><span>        { 0, NULL }</span><br><span> };</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static void ns2_free_nse(struct gprs_ns2_nse *nse);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! string-format a given NS-VC into a user-supplied buffer.</span><br><span>  *  \param[in] buf user-allocated output buffer</span><br><span>  *  \param[in] buf_len size of user-allocated output buffer in bytes</span><br><span>@@ -631,9 +633,9 @@</span><br><span>  *  \param[in] nsvc NS-VC to destroy */</span><br><span> void gprs_ns2_free_nsvc(struct gprs_ns2_vc *nsvc)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-      if (!nsvc)</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!nsvc || nsvc->freed)</span><br><span>                 return;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(120, 100%, 40%);">+       nsvc->freed = true;</span><br><span>       ns2_prim_status_ind(nsvc->nse, nsvc, 0, GPRS_NS2_AFF_CAUSE_VC_FAILURE);</span><br><span> </span><br><span>       llist_del(&nsvc->list);</span><br><span>@@ -661,14 +663,18 @@</span><br><span>  */</span><br><span> void gprs_ns2_free_nsvcs(struct gprs_ns2_nse *nse)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-        struct gprs_ns2_vc *nsvc, *tmp;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct gprs_ns2_vc *nsvc;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   if (!nse)</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!nse || nse->freed)</span><br><span>           return;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     llist_for_each_entry_safe(nsvc, tmp, &nse->nsvc, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+       ns2_get(nse, NSE_USE_LIST);</span><br><span style="color: hsl(120, 100%, 40%);">+loop:</span><br><span style="color: hsl(120, 100%, 40%);">+    llist_for_each_entry(nsvc, &nse->nsvc, list) {</span><br><span>                gprs_ns2_free_nsvc(nsvc);</span><br><span style="color: hsl(120, 100%, 40%);">+             goto loop;</span><br><span>   }</span><br><span style="color: hsl(120, 100%, 40%);">+     ns2_put(nse, NSE_USE_LIST);</span><br><span> }</span><br><span> </span><br><span> /*! Allocate a message buffer for use with the NS2 stack. */</span><br><span>@@ -778,6 +784,30 @@</span><br><span>  return NULL;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static int nse_use_cb(struct osmo_use_count_entry *e, int32_t old_use_count, const char *file, int line)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    struct gprs_ns2_nse *nse = e->use_count->talloc_object;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_use_count_entry *e2;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    int32_t other_count = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+      int32_t core_count = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!e->use)</span><br><span style="color: hsl(120, 100%, 40%);">+               return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+       if (e->count < 0)</span><br><span style="color: hsl(120, 100%, 40%);">+               return -ERANGE;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     llist_for_each_entry(e2, &nse->use_count.use_counts, entry) {</span><br><span style="color: hsl(120, 100%, 40%);">+          if (strcmp(e2->use, NSE_USE_CORE) == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                    core_count += e2->count;</span><br><span style="color: hsl(120, 100%, 40%);">+           else</span><br><span style="color: hsl(120, 100%, 40%);">+                  other_count += e2->count;</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%);">+   if (other_count <= 0 && core_count <= 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                ns2_free_nse(nse);</span><br><span style="color: hsl(120, 100%, 40%);">+    return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! Create a NS Entity within given NS instance.</span><br><span>  *  \param[in] nsi NS instance in which to create NS Entity</span><br><span>  *  \param[in] nsei NS Entity Identifier of to-be-created NSE</span><br><span>@@ -813,6 +843,11 @@</span><br><span>    nse->mtu = 0;</span><br><span>     llist_add_tail(&nse->list, &nsi->nse);</span><br><span>         INIT_LLIST_HEAD(&nse->nsvc);</span><br><span style="color: hsl(120, 100%, 40%);">+   nse->use_count = (struct osmo_use_count){</span><br><span style="color: hsl(120, 100%, 40%);">+          .talloc_object = nse,</span><br><span style="color: hsl(120, 100%, 40%);">+         .use_cb = nse_use_cb,</span><br><span style="color: hsl(120, 100%, 40%);">+ };</span><br><span style="color: hsl(120, 100%, 40%);">+    ns2_get(nse, NSE_USE_CORE);</span><br><span> </span><br><span>      return nse;</span><br><span> }</span><br><span>@@ -871,26 +906,35 @@</span><br><span>     return nse->nsei;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/*! Destroy given NS Entity.</span><br><span style="color: hsl(0, 100%, 40%);">- *  \param[in] nse NS Entity to destroy */</span><br><span style="color: hsl(0, 100%, 40%);">-void gprs_ns2_free_nse(struct gprs_ns2_nse *nse)</span><br><span style="color: hsl(120, 100%, 40%);">+static void ns2_free_nse(struct gprs_ns2_nse *nse)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-    if (!nse)</span><br><span style="color: hsl(120, 100%, 40%);">+     struct gprs_ns2_vc *nsvc, *nsvc2;</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!nse || nse->freed)</span><br><span>           return;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+   nse->freed = true;</span><br><span>        nse->alive = false;</span><br><span>       if (nse->bss_sns_fi) {</span><br><span>            osmo_fsm_inst_term(nse->bss_sns_fi, OSMO_FSM_TERM_REQUEST, NULL);</span><br><span>                 nse->bss_sns_fi = NULL;</span><br><span>   }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   gprs_ns2_free_nsvcs(nse);</span><br><span style="color: hsl(0, 100%, 40%);">-       ns2_prim_status_ind(nse, NULL, 0, GPRS_NS2_AFF_CAUSE_FAILURE);</span><br><span style="color: hsl(120, 100%, 40%);">+        llist_for_each_entry_safe(nsvc, nsvc2, &nse->nsvc, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+             gprs_ns2_free_nsvc(nsvc);</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ ns2_prim_status_ind(nse, NULL, 0, GPRS_NS2_AFF_CAUSE_FAILURE);</span><br><span>       llist_del(&nse->list);</span><br><span>        talloc_free(nse);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! Destroy given NS Entity.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] nse NS Entity to destroy */</span><br><span style="color: hsl(120, 100%, 40%);">+void gprs_ns2_free_nse(struct gprs_ns2_nse *nse)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     ns2_put(nse, NSE_USE_CORE);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> void gprs_ns2_free_nses(struct gprs_ns2_inst *nsi)</span><br><span> {</span><br><span>  struct gprs_ns2_nse *nse, *ntmp;</span><br><span>@@ -1240,11 +1284,14 @@</span><br><span> {</span><br><span>      struct gprs_ns2_vc *nsvc, *tmp;</span><br><span>      int rc = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ns2_get(nse, NSE_USE_LIST);</span><br><span>  llist_for_each_entry_safe(nsvc, tmp, &nse->nsvc, list) {</span><br><span>              rc = cb(nsvc, cb_data);</span><br><span>              if (rc < 0)</span><br><span>                       return rc;</span><br><span>   }</span><br><span style="color: hsl(120, 100%, 40%);">+     ns2_put(nse, NSE_USE_LIST);</span><br><span> </span><br><span>      return 0;</span><br><span> }</span><br><span>@@ -1450,20 +1497,26 @@</span><br><span> void gprs_ns2_free_bind(struct gprs_ns2_vc_bind *bind)</span><br><span> {</span><br><span>      struct gprs_ns2_vc *nsvc, *tmp;</span><br><span style="color: hsl(0, 100%, 40%);">- struct gprs_ns2_nse *nse;</span><br><span style="color: hsl(0, 100%, 40%);">-       if (!bind)</span><br><span style="color: hsl(120, 100%, 40%);">+    struct gprs_ns2_nse *nse, *nse2;</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!bind || bind->freed)</span><br><span>                 return;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     llist_for_each_entry_safe(nsvc, tmp, &bind->nsvc, blist) {</span><br><span style="color: hsl(0, 100%, 40%);">-               gprs_ns2_free_nsvc(nsvc);</span><br><span style="color: hsl(0, 100%, 40%);">-       }</span><br><span style="color: hsl(120, 100%, 40%);">+     bind->freed = true;</span><br><span> </span><br><span>   if (gprs_ns2_is_ip_bind(bind)) {</span><br><span style="color: hsl(0, 100%, 40%);">-                llist_for_each_entry(nse, &bind->nsi->nse, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+          llist_for_each_entry_safe(nse, nse2, &bind->nsi->nse, list) {</span><br><span>                      gprs_ns2_sns_del_bind(nse, bind);</span><br><span>            }</span><br><span>    }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       /* because freeing a single nsvc might free all other nsvcs */</span><br><span style="color: hsl(120, 100%, 40%);">+loop:</span><br><span style="color: hsl(120, 100%, 40%);">+ llist_for_each_entry(nsvc, &bind->nsvc, blist) {</span><br><span style="color: hsl(120, 100%, 40%);">+               gprs_ns2_free_nsvc(nsvc);</span><br><span style="color: hsl(120, 100%, 40%);">+             goto loop;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  if (bind->driver->free_bind)</span><br><span>           bind->driver->free_bind(bind);</span><br><span> </span><br><span>diff --git a/src/gb/gprs_ns2_internal.h b/src/gb/gprs_ns2_internal.h</span><br><span>index 70e212a..65cfda6 100644</span><br><span>--- a/src/gb/gprs_ns2_internal.h</span><br><span>+++ b/src/gb/gprs_ns2_internal.h</span><br><span>@@ -6,6 +6,7 @@</span><br><span> #include <stdint.h></span><br><span> </span><br><span> #include <osmocom/core/logging.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/use_count.h></span><br><span> #include <osmocom/gprs/protocol/gsm_08_16.h></span><br><span> #include <osmocom/gprs/gprs_ns2.h></span><br><span> </span><br><span>@@ -198,6 +199,11 @@</span><br><span> </span><br><span>      /*! are we implementing the SGSN role? */</span><br><span>    bool ip_sns_role_sgsn;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /*! recursive anchor */</span><br><span style="color: hsl(120, 100%, 40%);">+       bool freed;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_use_count use_count;</span><br><span> };</span><br><span> </span><br><span> /*! Structure representing a single NS-VC */</span><br><span>@@ -242,6 +248,9 @@</span><br><span>     enum gprs_ns2_vc_mode mode;</span><br><span> </span><br><span>      struct osmo_fsm_inst *fi;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /*! recursive anchor */</span><br><span style="color: hsl(120, 100%, 40%);">+       bool freed;</span><br><span> };</span><br><span> </span><br><span> /*! Structure repesenting a bind instance. E.g. IPv4 listen port. */</span><br><span>@@ -286,6 +295,9 @@</span><br><span>  uint8_t sns_data_weight;</span><br><span> </span><br><span>         struct osmo_stat_item_group *statg;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /*! recursive anchor */</span><br><span style="color: hsl(120, 100%, 40%);">+       bool freed;</span><br><span> };</span><br><span> </span><br><span> struct gprs_ns2_vc_driver {</span><br><span>@@ -294,6 +306,15 @@</span><br><span>  void (*free_bind)(struct gprs_ns2_vc_bind *driver);</span><br><span> };</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#define ns2_get(ns2_obj, use) \</span><br><span style="color: hsl(120, 100%, 40%);">+        OSMO_ASSERT(osmo_use_count_get_put(&(ns2_obj)->use_count, use, 1) == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+#define ns2_put(ns2_obj, use) \</span><br><span style="color: hsl(120, 100%, 40%);">+       OSMO_ASSERT(osmo_use_count_get_put(&(ns2_obj)->use_count, use, -1) == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+#define NSE_USE_CORE "ns2core"</span><br><span style="color: hsl(120, 100%, 40%);">+#define NSE_USE_LIST "ns2list"</span><br><span style="color: hsl(120, 100%, 40%);">+#define NSE_USE_SNS "ns2sns"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> enum ns2_cs ns2_create_vc(struct gprs_ns2_vc_bind *bind,</span><br><span>                         struct msgb *msg,</span><br><span>                            const struct osmo_sockaddr *remote,</span><br><span>diff --git a/src/gb/gprs_ns2_sns.c b/src/gb/gprs_ns2_sns.c</span><br><span>index 642b47c..b4a8d7f 100644</span><br><span>--- a/src/gb/gprs_ns2_sns.c</span><br><span>+++ b/src/gb/gprs_ns2_sns.c</span><br><span>@@ -658,6 +658,7 @@</span><br><span>            OSMO_ASSERT(false);</span><br><span>  }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ ns2_get(nse, NSE_USE_LIST);</span><br><span>  llist_for_each_entry_safe(nsvc, tmp, &nse->nsvc, list) {</span><br><span>              remote = gprs_ns2_ip_vc_remote(nsvc);</span><br><span>                /* all nsvc in NSE should be IP/UDP nsvc */</span><br><span>@@ -668,6 +669,7 @@</span><br><span>            LOGPFSML(fi, LOGL_INFO, "DELETE NS-VC %s\n", gprs_ns2_ll_str(nsvc));</span><br><span>               gprs_ns2_free_nsvc(nsvc);</span><br><span>    }</span><br><span style="color: hsl(120, 100%, 40%);">+     ns2_put(nse, NSE_USE_LIST);</span><br><span> </span><br><span>      return 0;</span><br><span> }</span><br><span>@@ -1482,6 +1484,7 @@</span><br><span>       struct ns2_sns_bind *sbind;</span><br><span>  struct gprs_ns2_vc *nsvc, *nsvc2;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ ns2_get(nse, NSE_USE_SNS);</span><br><span>   switch (event) {</span><br><span>     case GPRS_SNS_EV_REQ_ADD_BIND:</span><br><span>               sbind = data;</span><br><span>@@ -1528,6 +1531,7 @@</span><br><span>                talloc_free(sbind);</span><br><span>          break;</span><br><span>       }</span><br><span style="color: hsl(120, 100%, 40%);">+     ns2_put(nse, NSE_USE_SNS);</span><br><span> }</span><br><span> </span><br><span> /* validate the bss configuration (sns endpoint and binds)</span><br><span>diff --git a/tests/gb/gprs_ns2_test.c b/tests/gb/gprs_ns2_test.c</span><br><span>index 515d908..2322735 100644</span><br><span>--- a/tests/gb/gprs_ns2_test.c</span><br><span>+++ b/tests/gb/gprs_ns2_test.c</span><br><span>@@ -642,6 +642,43 @@</span><br><span>        printf("--- Finish force unconfigured test\n");</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+void test_use_count(void *ctx)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gprs_ns2_inst *nsi;</span><br><span style="color: hsl(120, 100%, 40%);">+    struct gprs_ns2_vc_bind *bind[2];</span><br><span style="color: hsl(120, 100%, 40%);">+     struct gprs_ns2_vc_bind *loopbind;</span><br><span style="color: hsl(120, 100%, 40%);">+    struct gprs_ns2_nse *nse;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct gprs_ns2_vc *nsvc[2];</span><br><span style="color: hsl(120, 100%, 40%);">+  struct gprs_ns2_vc *loop[2];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        struct msgb *msg, *other;</span><br><span style="color: hsl(120, 100%, 40%);">+     char idbuf[32];</span><br><span style="color: hsl(120, 100%, 40%);">+       int i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      printf("--- Testing nse use count\n");</span><br><span style="color: hsl(120, 100%, 40%);">+      osmo_wqueue_clear(unitdata);</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("---- Create Binds\n");</span><br><span style="color: hsl(120, 100%, 40%);">+      nsi = gprs_ns2_instantiate(ctx, ns_prim_cb, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+    bind[0] = dummy_bind(nsi, "bblock1");</span><br><span style="color: hsl(120, 100%, 40%);">+       bind[1] = dummy_bind(nsi, "bblock2");</span><br><span style="color: hsl(120, 100%, 40%);">+       loopbind = loopback_bind(nsi, "loopback");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        // free SNS NSE with active NSVCs</span><br><span style="color: hsl(120, 100%, 40%);">+     // free SNS NSE with active NSVCs on a SNS/NSE event</span><br><span style="color: hsl(120, 100%, 40%);">+  // free a dynamic SNS NSE</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   nse = gprs_ns2_create_nse(nsi, 1004, GPRS_NS2_LL_UDP, GPRS_NS2_DIALECT_STATIC_RESETBLOCK);</span><br><span style="color: hsl(120, 100%, 40%);">+    OSMO_ASSERT(nse);</span><br><span style="color: hsl(120, 100%, 40%);">+     for (i=0; i<2; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+              printf("---- Create NSVC[%d]\n", i);</span><br><span style="color: hsl(120, 100%, 40%);">+                snprintf(idbuf, sizeof(idbuf), "NSE%05u-dummy-%i", nse->nsei, i);</span><br><span style="color: hsl(120, 100%, 40%);">+                nsvc[i] = ns2_vc_alloc(bind[i], nse, false, GPRS_NS2_VC_MODE_BLOCKRESET, idbuf);</span><br><span style="color: hsl(120, 100%, 40%);">+              OSMO_ASSERT(nsvc[i]);</span><br><span style="color: hsl(120, 100%, 40%);">+         ns2_vc_fsm_start(nsvc[i]);</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+     gprs_ns2_free_nse(nse);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> int main(int argc, char **argv)</span><br><span> {</span><br><span>         void *ctx = talloc_named_const(NULL, 0, "gprs_ns2_test");</span><br><span>@@ -663,6 +700,7 @@</span><br><span>    test_unitdata_weights(ctx);</span><br><span>  test_unconfigured(ctx);</span><br><span>      test_mtu(ctx);</span><br><span style="color: hsl(120, 100%, 40%);">+        test_use_count(ctx);</span><br><span>         printf("===== NS2 protocol test END\n\n");</span><br><span> </span><br><span>     talloc_free(ctx);</span><br><span>diff --git a/tests/gb/gprs_ns2_test.ok b/tests/gb/gprs_ns2_test.ok</span><br><span>index 8bae5b9..f4af60c 100644</span><br><span>--- a/tests/gb/gprs_ns2_test.ok</span><br><span>+++ b/tests/gb/gprs_ns2_test.ok</span><br><span>@@ -47,5 +47,9 @@</span><br><span> ---- Send a small UNITDATA to NSVC[0]</span><br><span> ---- Check if got mtu reported</span><br><span> --- Finish unitdata test</span><br><span style="color: hsl(120, 100%, 40%);">+--- Testing nse use count</span><br><span style="color: hsl(120, 100%, 40%);">+---- Create Binds</span><br><span style="color: hsl(120, 100%, 40%);">+---- Create NSVC[0]</span><br><span style="color: hsl(120, 100%, 40%);">+---- Create NSVC[1]</span><br><span> ===== NS2 protocol test END</span><br><span> </span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/libosmocore/+/24923">change 24923</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/libosmocore/+/24923"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: libosmocore </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I03cb2419926c639d4bd357a33ce8008c50cd3bee </div>
<div style="display:none"> Gerrit-Change-Number: 24923 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: lynxis lazus <lynxis@fe80.eu> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>