Change in libosmocore[master]: gprs_ns2: set transfer cap in NS Status primitive

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

laforge gerrit-no-reply at lists.osmocom.org
Tue Jan 5 14:24:03 UTC 2021


laforge has submitted this change. ( https://gerrit.osmocom.org/c/libosmocore/+/21753 )

Change subject: gprs_ns2: set transfer cap in NS Status primitive
......................................................................

gprs_ns2: set transfer cap in NS Status primitive

Related: SYS#5153 OS#4835
Change-Id: Ia1046db9e0d50855bff9de670b612ffc57af9995
---
M src/gb/Makefile.am
M src/gb/gprs_ns2.c
M src/gb/gprs_ns2_fr.c
M src/gb/gprs_ns2_frgre.c
M src/gb/gprs_ns2_internal.h
M src/gb/gprs_ns2_udp.c
M tests/Makefile.am
A tests/gb/gprs_ns2_test.c
A tests/gb/gprs_ns2_test.ok
M tests/testsuite.at
10 files changed, 276 insertions(+), 2 deletions(-)

Approvals:
  daniel: Looks good to me, but someone else must approve
  pespin: Looks good to me, approved
  Jenkins Builder: Verified



diff --git a/src/gb/Makefile.am b/src/gb/Makefile.am
index c829c29..cbee333 100644
--- a/src/gb/Makefile.am
+++ b/src/gb/Makefile.am
@@ -28,6 +28,12 @@
 		  gprs_ns2_message.c gprs_ns2_vty.c gprs_ns2_vty2.c \
 		  gprs_bssgp2.c bssgp_bvc_fsm.c \
 		  common_vty.c frame_relay.c
+
+# convenience library for testing with access to all non-static symbols
+noinst_LTLIBRARIES = libosmogb-test.la
+libosmogb_test_la_LIBADD = $(libosmogb_la_LIBADD)
+libosmogb_test_la_SOURCES= $(libosmogb_la_SOURCES)
+
 endif
 
 EXTRA_DIST = libosmogb.map
diff --git a/src/gb/gprs_ns2.c b/src/gb/gprs_ns2.c
index 1098f22..e43b636 100644
--- a/src/gb/gprs_ns2.c
+++ b/src/gb/gprs_ns2.c
@@ -471,7 +471,7 @@
 	nsp.nsei = nse->nsei;
 	nsp.bvci = bvci;
 	nsp.u.status.cause = cause;
-	nsp.u.status.transfer = -1;
+	nsp.u.status.transfer = ns2_count_transfer_cap(nse, bvci);
 	nsp.u.status.first = nse->first;
 	nsp.u.status.persistent = nse->persistent;
 	if (nsvc)
@@ -1263,4 +1263,68 @@
 	}
 }
 
+static void add_bind_array(struct gprs_ns2_vc_bind **array,
+			   struct gprs_ns2_vc_bind *bind, int size)
+{
+	int i;
+	for (i=0; i < size; i++) {
+		if (array[i] == bind)
+			return;
+		if (!array[i])
+			break;
+	}
+
+	if (i == size)
+		return;
+
+	array[i] = bind;
+}
+
+/*! calculate the transfer capabilities for a nse
+ *  \param nse the nse to count the transfer capability
+ *  \param bvci a bvci - unused
+ *  \return the transfer capability in mbit. On error < 0.
+ */
+int ns2_count_transfer_cap(struct gprs_ns2_nse *nse,
+			   uint16_t bvci)
+{
+	struct gprs_ns2_vc *nsvc;
+	struct gprs_ns2_vc_bind **active_binds;
+	int i, active_nsvcs = 0, transfer_cap = 0;
+
+	/* calculate the transfer capabilities based on the binds.
+	 * A bind has a transfer capability which is shared across all NSVCs.
+	 * Take care the bind cap is not counted twice within a NSE.
+	 * This should be accurate for FR and UDP but not for FR/GRE. */
+
+	if (!nse->alive)
+		return 0;
+
+	llist_for_each_entry(nsvc, &nse->nsvc, list) {
+		if (gprs_ns2_vc_is_unblocked(nsvc))
+			active_nsvcs++;
+	}
+	/* an alive nse should always have active_nsvcs */
+	OSMO_ASSERT(active_nsvcs);
+
+	active_binds = talloc_zero_array(nse, struct gprs_ns2_vc_bind*, active_nsvcs);
+	if (!active_binds)
+		return -ENOMEM;
+
+	llist_for_each_entry(nsvc, &nse->nsvc, list) {
+		if (!gprs_ns2_vc_is_unblocked(nsvc))
+			continue;
+		add_bind_array(active_binds, nsvc->bind, active_nsvcs);
+	}
+
+	/* TODO: change calcuation for FR/GRE */
+	for (i = 0; i < active_nsvcs; i++) {
+		if (active_binds[i])
+			transfer_cap += active_binds[i]->transfer_capability;
+	}
+
+	talloc_free(active_binds);
+	return transfer_cap;
+}
+
 /*! @} */
diff --git a/src/gb/gprs_ns2_fr.c b/src/gb/gprs_ns2_fr.c
index e972a34..ca2d38c 100644
--- a/src/gb/gprs_ns2_fr.c
+++ b/src/gb/gprs_ns2_fr.c
@@ -579,6 +579,8 @@
 
 	bind->driver = &vc_driver_fr;
 	bind->ll = GPRS_NS2_LL_FR;
+	/* 2 mbit */
+	bind->transfer_capability = 2;
 	bind->send_vc = fr_vc_sendmsg;
 	bind->free_vc = free_vc;
 	bind->dump_vty = dump_vty;
diff --git a/src/gb/gprs_ns2_frgre.c b/src/gb/gprs_ns2_frgre.c
index 014517a..625d05c 100644
--- a/src/gb/gprs_ns2_frgre.c
+++ b/src/gb/gprs_ns2_frgre.c
@@ -569,6 +569,8 @@
 
 	bind->driver = &vc_driver_frgre;
 	bind->ll = GPRS_NS2_LL_FR_GRE;
+	/* 2 mbit transfer capability. Counting should be done different for this. */
+	bind->transfer_capability = 2;
 	bind->send_vc = frgre_vc_sendmsg;
 	bind->free_vc = free_vc;
 	bind->nsi = nsi;
diff --git a/src/gb/gprs_ns2_internal.h b/src/gb/gprs_ns2_internal.h
index 4c0cdd0..c33f7f8 100644
--- a/src/gb/gprs_ns2_internal.h
+++ b/src/gb/gprs_ns2_internal.h
@@ -198,6 +198,9 @@
 	bool accept_ipaccess;
 	bool accept_sns;
 
+	/*! transfer capability in mbit */
+	int transfer_capability;
+
 	/*! which link-layer are we based on? */
 	enum gprs_ns2_ll ll;
 
@@ -312,3 +315,5 @@
 /* nse */
 void ns2_nse_notify_unblocked(struct gprs_ns2_vc *nsvc, bool unblocked);
 enum gprs_ns2_vc_mode gprs_ns2_dialect_to_vc_mode(enum gprs_ns2_dialect dialect);
+int ns2_count_transfer_cap(struct gprs_ns2_nse *nse,
+			   uint16_t bvci);
diff --git a/src/gb/gprs_ns2_udp.c b/src/gb/gprs_ns2_udp.c
index 9058279..370937f 100644
--- a/src/gb/gprs_ns2_udp.c
+++ b/src/gb/gprs_ns2_udp.c
@@ -336,6 +336,10 @@
 
 	bind->driver = &vc_driver_ip;
 	bind->ll = GPRS_NS2_LL_UDP;
+	/* expect 100 mbit at least.
+	 * TODO: ask the network layer about the speed. But would require
+	 * notification on change. */
+	bind->transfer_capability = 100;
 	bind->send_vc = nsip_vc_sendmsg;
 	bind->free_vc = free_vc;
 	bind->dump_vty = dump_vty;
diff --git a/tests/Makefile.am b/tests/Makefile.am
index dbca9d7..f769603 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -74,7 +74,7 @@
 endif
 
 if ENABLE_GB
-check_PROGRAMS += gb/bssgp_fc_test gb/gprs_bssgp_test gb/gprs_ns_test fr/fr_test
+check_PROGRAMS += gb/bssgp_fc_test gb/gprs_bssgp_test gb/gprs_ns_test gb/gprs_ns2_test fr/fr_test
 endif
 
 utils_utils_test_SOURCES = utils/utils_test.c
@@ -180,6 +180,16 @@
 			$(top_builddir)/src/vty/libosmovty.la \
 			$(top_builddir)/src/gsm/libosmogsm.la
 
+gb_gprs_ns2_test_SOURCES = gb/gprs_ns2_test.c
+gb_gprs_ns2_test_LDADD = $(LDADD) $(LIBRARY_DLSYM) \
+			$(top_builddir)/src/vty/libosmovty.la \
+			$(top_builddir)/src/gsm/libosmogsm.la \
+			$(top_builddir)/src/libosmocore.la \
+			$(top_builddir)/src/gb/libosmogb-test.la
+if ENABLE_LIBMNL
+gb_gprs_ns2_test_LDADD += $(LIBMNL_LIBS)
+endif
+
 logging_logging_test_SOURCES = logging/logging_test.c
 
 logging_logging_vty_test_SOURCES = logging/logging_vty_test.c
@@ -321,6 +331,7 @@
              gb/bssgp_fc_tests.ok gb/bssgp_fc_tests.sh			\
              gb/gprs_bssgp_test.ok gb/gprs_ns_test.ok gea/gea_test.ok	\
              gb/gprs_ns2_vty.vty gb/osmoappdesc.py gb/osmo-ns-dummy.cfg \
+             gb/gprs_ns2_test.ok					\
              gprs/gprs_test.ok kasumi/kasumi_test.ok			\
              msgfile/msgfile_test.ok msgfile/msgconfig.cfg		\
              logging/logging_test.ok logging/logging_test.err		\
diff --git a/tests/gb/gprs_ns2_test.c b/tests/gb/gprs_ns2_test.c
new file mode 100644
index 0000000..86a0190
--- /dev/null
+++ b/tests/gb/gprs_ns2_test.c
@@ -0,0 +1,164 @@
+/* test routines for NS connection handling
+ * (C) 2020 sysmocom - s.f.m.c. GmbH
+ * Author: Alexander Couzens <lynxis at fe80.eu>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#undef _GNU_SOURCE
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <string.h>
+#include <getopt.h>
+#include <dlfcn.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <osmocom/core/fsm.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/application.h>
+#include <osmocom/core/utils.h>
+#include <osmocom/core/logging.h>
+#include <osmocom/core/socket.h>
+#include <osmocom/core/talloc.h>
+#include <osmocom/core/write_queue.h>
+#include <osmocom/gprs/gprs_msgb.h>
+#include <osmocom/gprs/gprs_ns2.h>
+#include <osmocom/gprs/gprs_bssgp.h>
+
+#include "../../src/gb/gprs_ns2_internal.h"
+
+int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
+{
+	return -1;
+}
+
+static struct log_info info = {};
+
+static int ns_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
+{
+	return 0;
+}
+
+void free_bind(struct gprs_ns2_vc_bind *bind)
+{
+	OSMO_ASSERT(bind);
+	talloc_free(bind);
+}
+
+struct gprs_ns2_vc_driver vc_driver_dummy = {
+	.name = "GB UDP dummy",
+	.free_bind = free_bind,
+};
+
+static int vc_sendmsg(struct gprs_ns2_vc *nsvc, struct msgb *msg)
+{
+	struct gprs_ns2_vc_bind *bind = nsvc->bind;
+	struct osmo_wqueue *queue = bind->priv;
+
+	osmo_wqueue_enqueue(queue, msg);
+	return 0;
+}
+
+static struct gprs_ns2_vc_bind *dummy_bind(struct gprs_ns2_inst *nsi, const char *name)
+{
+	struct gprs_ns2_vc_bind *bind = talloc_zero(nsi, struct gprs_ns2_vc_bind);
+	OSMO_ASSERT(bind);
+
+	bind->name = talloc_strdup(bind, name);
+	bind->driver = &vc_driver_dummy;
+	bind->ll = GPRS_NS2_LL_UDP;
+	bind->transfer_capability = 42;
+	bind->nsi = nsi;
+	bind->send_vc = vc_sendmsg;
+	bind->priv = talloc_zero(bind, struct osmo_wqueue);
+	struct osmo_wqueue *queue = bind->priv;
+
+	INIT_LLIST_HEAD(&bind->nsvc);
+	llist_add(&bind->list, &nsi->binding);
+	osmo_wqueue_init(queue, 100);
+
+	return bind;
+}
+
+void test_nse_transfer_cap(void *ctx)
+{
+	struct gprs_ns2_inst *nsi;
+	struct gprs_ns2_vc_bind *bind[2];
+	struct gprs_ns2_nse *nse;
+	struct gprs_ns2_vc *nsvc[3];
+
+	/* create a UDP dummy bind[0] with transfer cap 42.
+	 * create nse (nsei 1001)
+	 * create 2x nsvc with the same bind.
+	 * nsvc[0] or nsvc[1] is alive (or both) cap == 42
+	 *
+	 * create a second bind with transfer cap == 23
+	 * create 3rd nsvc with bind[1]
+	 * transfer cap should be 42 + 23
+	 */
+
+	printf("--- Testing NSE transfer cap\n");
+
+	printf("---- Create NSE + Binds\n");
+	nsi = gprs_ns2_instantiate(ctx, ns_prim_cb, NULL);
+	bind[0] = dummy_bind(nsi, "transfercap1");
+	bind[1] = dummy_bind(nsi, "transfercap2");
+	bind[1]->transfer_capability = 23;
+	nse = gprs_ns2_create_nse(nsi, 1001, GPRS_NS2_LL_UDP, NS2_DIALECT_STATIC_ALIVE);
+	OSMO_ASSERT(nse);
+
+	printf("---- Test with NSVC[0]\n");
+	nsvc[0] = ns2_vc_alloc(bind[0], nse, false, NS2_VC_MODE_ALIVE);
+	OSMO_ASSERT(nsvc[0]);
+	OSMO_ASSERT(ns2_count_transfer_cap(nse, 0) == 0);
+	nsvc[0]->fi->state = 3;	/* HACK: 3 = GPRS_NS2_ST_UNBLOCKED */
+	ns2_nse_notify_unblocked(nsvc[0], true);
+	OSMO_ASSERT(ns2_count_transfer_cap(nse, 0) == 42);
+
+	printf("---- Test with NSVC[1]\n");
+	nsvc[1] = ns2_vc_alloc(bind[0], nse, false, NS2_VC_MODE_ALIVE);
+	OSMO_ASSERT(nsvc[1]);
+	OSMO_ASSERT(ns2_count_transfer_cap(nse, 0) == 42);
+	nsvc[1]->fi->state = 3; /* HACK: 3 = GPRS_NS2_ST_UNBLOCKED */
+	ns2_nse_notify_unblocked(nsvc[1], true);
+	OSMO_ASSERT(ns2_count_transfer_cap(nse, 0) == 42);
+
+	printf("---- Test with NSVC[2]\n");
+	nsvc[2] = ns2_vc_alloc(bind[1], nse, false, NS2_VC_MODE_ALIVE);
+	OSMO_ASSERT(nsvc[2]);
+	OSMO_ASSERT(ns2_count_transfer_cap(nse, 0) == 42);
+	nsvc[2]->fi->state = 3; /* HACK: 3 = GPRS_NS2_ST_UNBLOCKED */
+	ns2_nse_notify_unblocked(nsvc[2], true);
+	OSMO_ASSERT(ns2_count_transfer_cap(nse, 0) == 42 + 23);
+
+	printf("---- Test with NSVC[1] removed\n");
+	/* reset nsvc[1] to be unconfigured - shouldn't change anything */
+	nsvc[1]->fi->state = 0; /* HACK: 0 = GPRS_NS2_ST_UNCONFIGURED */
+	ns2_nse_notify_unblocked(nsvc[1], false);
+	OSMO_ASSERT(ns2_count_transfer_cap(nse, 0) == 42 + 23);
+
+	printf("--- Finish NSE transfer cap\n");
+
+}
+
+int main(int argc, char **argv)
+{
+	void *ctx = talloc_named_const(NULL, 0, "gprs_ns2_test");
+	osmo_init_logging2(ctx, &info);
+	log_set_use_color(osmo_stderr_target, 0);
+	log_set_print_filename(osmo_stderr_target, 0);
+	log_set_print_filename(osmo_stderr_target, 0);
+	log_set_log_level(osmo_stderr_target, LOGL_INFO);
+	setlinebuf(stdout);
+
+	printf("===== NS2 protocol test START\n");
+	test_nse_transfer_cap(ctx);
+	printf("===== NS2 protocol test END\n\n");
+
+	exit(EXIT_SUCCESS);
+}
diff --git a/tests/gb/gprs_ns2_test.ok b/tests/gb/gprs_ns2_test.ok
new file mode 100644
index 0000000..62bbbfe
--- /dev/null
+++ b/tests/gb/gprs_ns2_test.ok
@@ -0,0 +1,10 @@
+===== NS2 protocol test START
+--- Testing NSE transfer cap
+---- Create NSE + Binds
+---- Test with NSVC[0]
+---- Test with NSVC[1]
+---- Test with NSVC[2]
+---- Test with NSVC[1] removed
+--- Finish NSE transfer cap
+===== NS2 protocol test END
+
diff --git a/tests/testsuite.at b/tests/testsuite.at
index 43f515a..ad93e16 100644
--- a/tests/testsuite.at
+++ b/tests/testsuite.at
@@ -221,6 +221,12 @@
 AT_CHECK([$abs_top_builddir/tests/gb/gprs_ns_test], [0], [expout], [ignore])
 AT_CLEANUP
 
+AT_SETUP([gprs-ns2])
+AT_KEYWORDS([gprs-ns2])
+cat $abs_srcdir/gb/gprs_ns2_test.ok > expout
+AT_CHECK([$abs_top_builddir/tests/gb/gprs_ns2_test], [0], [expout], [ignore])
+AT_CLEANUP
+
 AT_SETUP([utils])
 AT_KEYWORDS([utils])
 cat $abs_srcdir/utils/utils_test.ok > expout

-- 
To view, visit https://gerrit.osmocom.org/c/libosmocore/+/21753
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: libosmocore
Gerrit-Branch: master
Gerrit-Change-Id: Ia1046db9e0d50855bff9de670b612ffc57af9995
Gerrit-Change-Number: 21753
Gerrit-PatchSet: 9
Gerrit-Owner: lynxis lazus <lynxis at fe80.eu>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: daniel <dwillmann at sysmocom.de>
Gerrit-Reviewer: laforge <laforge at osmocom.org>
Gerrit-Reviewer: lynxis lazus <lynxis at fe80.eu>
Gerrit-Reviewer: pespin <pespin at sysmocom.de>
Gerrit-MessageType: merged
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20210105/4870461d/attachment.htm>


More information about the gerrit-log mailing list