diff options
-rw-r--r-- | src/gb/Makefile.am | 6 | ||||
-rw-r--r-- | src/gb/gprs_ns2.c | 66 | ||||
-rw-r--r-- | src/gb/gprs_ns2_fr.c | 2 | ||||
-rw-r--r-- | src/gb/gprs_ns2_frgre.c | 2 | ||||
-rw-r--r-- | src/gb/gprs_ns2_internal.h | 5 | ||||
-rw-r--r-- | src/gb/gprs_ns2_udp.c | 4 | ||||
-rw-r--r-- | tests/Makefile.am | 13 | ||||
-rw-r--r-- | tests/gb/gprs_ns2_test.c | 164 | ||||
-rw-r--r-- | tests/gb/gprs_ns2_test.ok | 10 | ||||
-rw-r--r-- | tests/testsuite.at | 6 |
10 files changed, 276 insertions, 2 deletions
diff --git a/src/gb/Makefile.am b/src/gb/Makefile.am index c829c293..cbee3338 100644 --- a/src/gb/Makefile.am +++ b/src/gb/Makefile.am @@ -28,6 +28,12 @@ libosmogb_la_SOURCES = gprs_ns.c gprs_ns_frgre.c gprs_ns_vty.c gprs_ns_sns.c \ 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 1098f221..e43b6365 100644 --- a/src/gb/gprs_ns2.c +++ b/src/gb/gprs_ns2.c @@ -471,7 +471,7 @@ void ns2_prim_status_ind(struct gprs_ns2_nse *nse, 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 @@ enum gprs_ns2_vc_mode gprs_ns2_dialect_to_vc_mode( } } +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 e972a343..ca2d38cf 100644 --- a/src/gb/gprs_ns2_fr.c +++ b/src/gb/gprs_ns2_fr.c @@ -579,6 +579,8 @@ int gprs_ns2_fr_bind(struct gprs_ns2_inst *nsi, 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 014517aa..625d05cf 100644 --- a/src/gb/gprs_ns2_frgre.c +++ b/src/gb/gprs_ns2_frgre.c @@ -569,6 +569,8 @@ int gprs_ns2_frgre_bind(struct gprs_ns2_inst *nsi, 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 4c0cdd01..c33f7f8a 100644 --- a/src/gb/gprs_ns2_internal.h +++ b/src/gb/gprs_ns2_internal.h @@ -198,6 +198,9 @@ struct gprs_ns2_vc_bind { 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 @@ int gprs_ns2_vc_is_unblocked(struct gprs_ns2_vc *nsvc); /* 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 90582794..370937f5 100644 --- a/src/gb/gprs_ns2_udp.c +++ b/src/gb/gprs_ns2_udp.c @@ -336,6 +336,10 @@ int gprs_ns2_ip_bind(struct gprs_ns2_inst *nsi, 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 dbca9d72..f769603f 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -74,7 +74,7 @@ check_PROGRAMS += \ 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 @@ gb_gprs_ns_test_LDADD = $(LDADD) $(top_builddir)/src/gb/libosmogb.la $(LIBRARY_D $(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 @@ EXTRA_DIST = testsuite.at $(srcdir)/package.m4 $(TESTSUITE) \ 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 00000000..86a01902 --- /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@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 00000000..62bbbfe7 --- /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 43f515af..ad93e164 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -221,6 +221,12 @@ cat $abs_srcdir/gb/gprs_ns_test.ok > expout 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 |