<p>lynxis lazus has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/libosmocore/+/22901">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">gprs_ns2: implement a simple load sharing for UDP<br><br>Implement the load sharing based on modulo of the LSP. As long the gprs_ns2 doesn't<br>support the resource distribution function (48.016 ยง 4.4a) this simple<br>approach is good enought.<br><br>Fixes: OS#4836<br>Change-Id: I8c2fe5d647694886ac600470fca6ea5d5d210a85<br>---<br>M src/gb/gprs_ns2.c<br>M tests/gb/gprs_ns2_test.c<br>M tests/gb/gprs_ns2_test.ok<br>3 files changed, 128 insertions(+), 1 deletion(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/01/22901/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 c7b963e..34c4c20 100644</span><br><span>--- a/src/gb/gprs_ns2.c</span><br><span>+++ b/src/gb/gprs_ns2.c</span><br><span>@@ -383,6 +383,31 @@</span><br><span>         return NULL;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/* 4.4.2 Load Sharing function for the IP Sub-Network */</span><br><span style="color: hsl(120, 100%, 40%);">+static struct gprs_ns2_vc *ns2_load_sharing_weight_modulor(</span><br><span style="color: hsl(120, 100%, 40%);">+          struct gprs_ns2_nse *nse,</span><br><span style="color: hsl(120, 100%, 40%);">+             uint16_t bvci,</span><br><span style="color: hsl(120, 100%, 40%);">+                uint32_t load_selector)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    struct gprs_ns2_vc *tmp;</span><br><span style="color: hsl(120, 100%, 40%);">+      uint32_t mod;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t i = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     if (nse->nsvc_count == 0)</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%);">+        mod = (bvci + load_selector) % nse->sum_data_weight;</span><br><span style="color: hsl(120, 100%, 40%);">+       llist_for_each_entry(tmp, &nse->nsvc, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+          if (!ns2_vc_is_unblocked(tmp))</span><br><span style="color: hsl(120, 100%, 40%);">+                        continue;</span><br><span style="color: hsl(120, 100%, 40%);">+             if (i == mod || mod < i + tmp->data_weight)</span><br><span style="color: hsl(120, 100%, 40%);">+                     return tmp;</span><br><span style="color: hsl(120, 100%, 40%);">+           i += tmp->data_weight;</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> /* pick the first available data NSVC - no load sharing */</span><br><span> struct gprs_ns2_vc *ns2_load_sharing_first(struct gprs_ns2_nse *nse)</span><br><span> {</span><br><span>@@ -420,7 +445,7 @@</span><br><span>                   nsvc = ns2_load_sharing_signal(nse);</span><br><span>                 } else {</span><br><span>                     /* data with load sharing parameter */</span><br><span style="color: hsl(0, 100%, 40%);">-                  nsvc = ns2_load_sharing_first(nse);</span><br><span style="color: hsl(120, 100%, 40%);">+                   nsvc = ns2_load_sharing_weight_modulor(nse, bvci, link_selector);</span><br><span>            }</span><br><span>            break;</span><br><span>       }</span><br><span>diff --git a/tests/gb/gprs_ns2_test.c b/tests/gb/gprs_ns2_test.c</span><br><span>index 6d71a8c..d8ed06f 100644</span><br><span>--- a/tests/gb/gprs_ns2_test.c</span><br><span>+++ b/tests/gb/gprs_ns2_test.c</span><br><span>@@ -60,6 +60,18 @@</span><br><span>  return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static int gp_send_to_ns(struct gprs_ns2_inst *nsi, struct msgb *msg, uint16_t nsei, uint16_t bvci, uint32_t lsp)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      struct osmo_gprs_ns2_prim nsp = {};</span><br><span style="color: hsl(120, 100%, 40%);">+   nsp.nsei = nsei;</span><br><span style="color: hsl(120, 100%, 40%);">+      nsp.bvci = bvci;</span><br><span style="color: hsl(120, 100%, 40%);">+      nsp.u.unitdata.link_selector = lsp;</span><br><span style="color: hsl(120, 100%, 40%);">+   osmo_prim_init(&nsp.oph, SAP_NS, GPRS_NS2_PRIM_UNIT_DATA,</span><br><span style="color: hsl(120, 100%, 40%);">+                 PRIM_OP_REQUEST, msg);</span><br><span style="color: hsl(120, 100%, 40%);">+        return gprs_ns2_recv_prim(nsi, &nsp.oph);</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%);">+</span><br><span> static struct msgb *get_pdu(struct gprs_ns2_vc_bind *bind, enum ns_pdu_type pdu_type)</span><br><span> {</span><br><span>   struct gprs_ns_hdr *nsh;</span><br><span>@@ -88,6 +100,12 @@</span><br><span>       return false;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static unsigned int count_pdus(struct gprs_ns2_vc_bind *bind)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      struct osmo_wqueue *queue = bind->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+    return llist_count(&queue->msg_queue);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static void clear_pdus(struct gprs_ns2_vc_bind *bind)</span><br><span> {</span><br><span>     struct osmo_wqueue *queue = bind->priv;</span><br><span>@@ -370,6 +388,81 @@</span><br><span>    printf("--- Finish unitdata test\n");</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+void test_unitdata_weights(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[3];</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[3];</span><br><span style="color: hsl(120, 100%, 40%);">+  struct gprs_ns2_vc *loop[3];</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 unitdata weight test\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 NSE + 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%);">+       bind[2] = dummy_bind(nsi, "bblock3");</span><br><span style="color: hsl(120, 100%, 40%);">+       loopbind = loopback_bind(nsi, "loopback");</span><br><span style="color: hsl(120, 100%, 40%);">+  nse = gprs_ns2_create_nse(nsi, 1004, GPRS_NS2_LL_UDP, GPRS_NS2_DIALECT_STATIC_ALIVE);</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%);">+   /* data weights are</span><br><span style="color: hsl(120, 100%, 40%);">+    * nsvc[0] = 1</span><br><span style="color: hsl(120, 100%, 40%);">+         * nsvc[1] = 2</span><br><span style="color: hsl(120, 100%, 40%);">+         * nsvc[2] = 3</span><br><span style="color: hsl(120, 100%, 40%);">+         */</span><br><span style="color: hsl(120, 100%, 40%);">+   for (i = 0; i < 3; 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_ALIVE, idbuf);</span><br><span style="color: hsl(120, 100%, 40%);">+           loop[i] = loopback_nsvc(loopbind, nsvc[i]);</span><br><span style="color: hsl(120, 100%, 40%);">+           OSMO_ASSERT(nsvc[i]);</span><br><span style="color: hsl(120, 100%, 40%);">+         nsvc[i]->data_weight = i + 1;</span><br><span style="color: hsl(120, 100%, 40%);">+              ns2_vc_fsm_start(nsvc[i]);</span><br><span style="color: hsl(120, 100%, 40%);">+            OSMO_ASSERT(!ns2_vc_is_unblocked(nsvc[i]));</span><br><span style="color: hsl(120, 100%, 40%);">+           ns2_tx_alive_ack(loop[i]);</span><br><span style="color: hsl(120, 100%, 40%);">+            OSMO_ASSERT(ns2_vc_is_unblocked(nsvc[i]));</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%);">+   /* all nsvcs are alive */</span><br><span style="color: hsl(120, 100%, 40%);">+     printf("---- Send UNITDATA to all NSVCs\n");</span><br><span style="color: hsl(120, 100%, 40%);">+        for (i = 0; i < 3; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+          msg = generate_unitdata("test_unitdata_weight");</span><br><span style="color: hsl(120, 100%, 40%);">+            ns2_recv_vc(nsvc[i], msg);</span><br><span style="color: hsl(120, 100%, 40%);">+            other = msgb_dequeue(&unitdata->msg_queue);</span><br><span style="color: hsl(120, 100%, 40%);">+            OSMO_ASSERT(msg == other);</span><br><span style="color: hsl(120, 100%, 40%);">+            other = msgb_dequeue(&unitdata->msg_queue);</span><br><span style="color: hsl(120, 100%, 40%);">+            OSMO_ASSERT(NULL == other);</span><br><span style="color: hsl(120, 100%, 40%);">+           msgb_free(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%);">+   /* nsvc[1] should be still good */</span><br><span style="color: hsl(120, 100%, 40%);">+    printf("---- Send BSSGP data to the NSE to test unitdata over NSVC[1]\n");</span><br><span style="color: hsl(120, 100%, 40%);">+  for (i = 0; i < 3; i++)</span><br><span style="color: hsl(120, 100%, 40%);">+            clear_pdus(bind[i]);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        for (i = 0; i < 12; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+         msg = generate_unitdata("test_unitdata_weight2");</span><br><span style="color: hsl(120, 100%, 40%);">+           gp_send_to_ns(nsi, msg, 1004, 1, i + 1);</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%);">+   for (i = 0; i < 3; i++)</span><br><span style="color: hsl(120, 100%, 40%);">+            fprintf(stderr, "count_pdus(bind[%d]) = %d\n", i, count_pdus(bind[i]));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   for (i = 0; i < 3; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+          OSMO_ASSERT(count_pdus(bind[i]) == nsvc[i]->data_weight * 2);</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%);">+   gprs_ns2_free(nsi);</span><br><span style="color: hsl(120, 100%, 40%);">+   printf("--- Finish unitdata weight test\n");</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> void test_mtu(void *ctx)</span><br><span> {</span><br><span>         struct gprs_ns2_inst *nsi;</span><br><span>@@ -440,6 +533,7 @@</span><br><span>     test_nse_transfer_cap(ctx);</span><br><span>  test_block_unblock_nsvc(ctx);</span><br><span>        test_unitdata(ctx);</span><br><span style="color: hsl(120, 100%, 40%);">+   test_unitdata_weights(ctx);</span><br><span>  test_mtu(ctx);</span><br><span>       printf("===== NS2 protocol test END\n\n");</span><br><span> </span><br><span>diff --git a/tests/gb/gprs_ns2_test.ok b/tests/gb/gprs_ns2_test.ok</span><br><span>index f40579f..cecc4bf 100644</span><br><span>--- a/tests/gb/gprs_ns2_test.ok</span><br><span>+++ b/tests/gb/gprs_ns2_test.ok</span><br><span>@@ -20,6 +20,14 @@</span><br><span> ---- Try to receive over blocked NSVC[0]</span><br><span> ---- Receive over NSVC[1]</span><br><span> --- Finish unitdata test</span><br><span style="color: hsl(120, 100%, 40%);">+--- Testing unitdata test</span><br><span style="color: hsl(120, 100%, 40%);">+---- Create NSE + 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 style="color: hsl(120, 100%, 40%);">+---- Create NSVC[2]</span><br><span style="color: hsl(120, 100%, 40%);">+---- Send UNITDATA to all NSVCs</span><br><span style="color: hsl(120, 100%, 40%);">+---- Send BSSGP data to the NSE to test unitdata over NSVC[1]</span><br><span style="color: hsl(120, 100%, 40%);">+--- Finish unitdata weight test</span><br><span> --- Testing mtu test</span><br><span> ---- Create NSE + Binds</span><br><span> ---- Create NSVC[0]</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/libosmocore/+/22901">change 22901</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/+/22901"/><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: I8c2fe5d647694886ac600470fca6ea5d5d210a85 </div>
<div style="display:none"> Gerrit-Change-Number: 22901 </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>