summaryrefslogtreecommitdiff
path: root/src/testing
diff options
context:
space:
mode:
Diffstat (limited to 'src/testing')
-rw-r--r--src/testing/Makefile.am12
-rw-r--r--src/testing/gnunet-cmds-helper.c20
-rwxr-xr-xsrc/testing/netjail_core_v2.sh260
-rwxr-xr-xsrc/testing/netjail_exec_v2.sh14
-rwxr-xr-xsrc/testing/netjail_start_v2.sh61
-rwxr-xr-xsrc/testing/netjail_stop_v2.sh59
-rw-r--r--src/testing/test_testing_api_cmd_netjail.c10
-rw-r--r--src/testing/testing.c381
-rw-r--r--src/testing/testing_api_cmd_netjail_start_testsystem.c20
-rw-r--r--src/testing/testing_api_cmd_netjail_start_testsystem_v2.c718
-rw-r--r--src/testing/testing_api_cmd_netjail_start_v2.c229
-rw-r--r--src/testing/testing_api_cmd_netjail_stop_testsystem_v2.c143
-rw-r--r--src/testing/testing_api_cmd_netjail_stop_v2.c225
-rwxr-xr-xsrc/testing/topo.sh95
14 files changed, 2217 insertions, 30 deletions
diff --git a/src/testing/Makefile.am b/src/testing/Makefile.am
index 038f0cb08..3e9d15986 100644
--- a/src/testing/Makefile.am
+++ b/src/testing/Makefile.am
@@ -45,9 +45,13 @@ libgnunettesting_la_SOURCES = \
testing_api_cmd_send_peer_ready.c \
testing_api_cmd_block_until_all_peers_started.c \
testing_api_cmd_netjail_start.c \
+ testing_api_cmd_netjail_start_v2.c \
testing_api_cmd_netjail_start_testsystem.c \
+ testing_api_cmd_netjail_start_testsystem_v2.c \
testing_api_cmd_netjail_stop_testsystem.c \
+ testing_api_cmd_netjail_stop_testsystem_v2.c \
testing_api_cmd_netjail_stop.c \
+ testing_api_cmd_netjail_stop_v2.c \
testing.c testing.h \
testing_api_cmd_system_create.c \
testing_api_cmd_system_destroy.c \
@@ -87,6 +91,7 @@ list_keys_LDADD = \
check_PROGRAMS = \
+ test_testing_topology \
test_testing_api_cmd_netjail \
test_testing_hello_world \
test_testing_portreservation \
@@ -98,6 +103,7 @@ check_PROGRAMS = \
if ENABLE_TEST_RUN
AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
TESTS = \
+ test_testing_topology \
test_testing_api_cmd_netjail \
test_testing_hello_world \
test_testing_portreservation \
@@ -106,6 +112,12 @@ TESTS = \
test_testing_servicestartup
endif
+test_testing_topology_SOURCES = \
+ test_testing_topology.c
+test_testing_topology_LDADD = \
+ libgnunettesting.la \
+ $(top_builddir)/src/util/libgnunetutil.la
+
test_testing_api_cmd_netjail_SOURCES = \
test_testing_api_cmd_netjail.c
test_testing_api_cmd_netjail_LDADD = \
diff --git a/src/testing/gnunet-cmds-helper.c b/src/testing/gnunet-cmds-helper.c
index 21ea33888..8f9e77709 100644
--- a/src/testing/gnunet-cmds-helper.c
+++ b/src/testing/gnunet-cmds-helper.c
@@ -163,14 +163,17 @@ struct WriteContext
size_t pos;
};
-struct Plugin *plugin;
-
/**
* The process handle to the testbed service
static struct GNUNET_OS_Process *cmd_binary_process;*/
/**
+ * Plugin to dynamically load a test case.
+ */
+struct Plugin *plugin;
+
+/**
* Handle to the testing system
*/
static struct GNUNET_TESTING_System *test_system;
@@ -329,6 +332,7 @@ write_message (struct GNUNET_MessageHeader *message, size_t msg_length)
static int
tokenizer_cb (void *cls, const struct GNUNET_MessageHeader *message)
{
+
struct NodeIdentifier *ni = cls;
const struct GNUNET_CMDS_HelperInit *msg;
struct GNUNET_CMDS_HelperReply *reply;
@@ -369,14 +373,14 @@ tokenizer_cb (void *cls, const struct GNUNET_MessageHeader *message)
plugin->n = ni->n;
plugin->m = ni->m;
- router_ip = GNUNET_malloc (strlen (ROUTER_BASE_IP) + strlen (plugin->m)
+ router_ip = GNUNET_malloc (strlen (ROUTER_BASE_IP) + strlen (plugin->n)
+ 1);
strcpy (router_ip, ROUTER_BASE_IP);
- strcat (router_ip, plugin->m);
+ strcat (router_ip, plugin->n);
- node_ip = GNUNET_malloc (strlen (NODE_BASE_IP) + strlen (plugin->n) + 1);
+ node_ip = GNUNET_malloc (strlen (NODE_BASE_IP) + strlen (plugin->m) + 1);
strcat (node_ip, NODE_BASE_IP);
- strcat (node_ip, plugin->n);
+ strcat (node_ip, plugin->m);
plugin->api->start_testcase (&write_message, router_ip, node_ip, plugin->m,
plugin->n, plugin->local_m);
@@ -533,8 +537,8 @@ main (int argc, char **argv)
ni = GNUNET_new (struct NodeIdentifier);
ni->global_n = argv[1];
ni->local_m = argv[2];
- ni->n = argv[3];
- ni->m = argv[4];
+ ni->m = argv[3];
+ ni->n = argv[4];
status = GNUNET_OK;
if (NULL ==
diff --git a/src/testing/netjail_core_v2.sh b/src/testing/netjail_core_v2.sh
new file mode 100755
index 000000000..ef0a54a5e
--- /dev/null
+++ b/src/testing/netjail_core_v2.sh
@@ -0,0 +1,260 @@
+#!/bin/sh
+#
+
+
+PREFIX=${PPID:?must run from a parent process}
+
+# running with `sudo` is required to be
+# able running the actual commands as the
+# original user.
+
+export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
+
+export RESULT=
+export NAMESPACE_NUM=0
+export INTERFACE_NUM=0
+
+netjail_next_namespace() {
+ local NUM=$NAMESPACE_NUM
+ NAMESPACE_NUM=$(($NAMESPACE_NUM + 1))
+ RESULT=$NUM
+}
+
+netjail_next_interface() {
+ local NUM=$INTERFACE_NUM
+ INTERFACE_NUM=$(($INTERFACE_NUM + 1))
+ RESULT=$NUM
+}
+
+netjail_opt() {
+ local OPT=$1
+ shift 1
+
+ INDEX=1
+
+ while [ $# -gt 0 ]; do
+ if [ "$1" = "$OPT" ]; then
+ RESULT=$INDEX
+ return
+ fi
+
+ INDEX=$(($INDEX + 1))
+ shift 1
+ done
+
+ RESULT=0
+}
+
+netjail_opts() {
+ local OPT=$1
+ local DEF=$2
+ shift 2
+
+ while [ $# -gt 0 ]; do
+ if [ "$1" = "$OPT" ]; then
+ printf "$2"
+ return
+ fi
+
+ shift 1
+ done
+
+ RESULT="$DEF"
+}
+
+netjail_check() {
+ local NODE_COUNT=$1
+ local FD_COUNT=$(($(ls /proc/self/fd | wc -w) - 4))
+
+ # quit if `$FD_COUNT < ($LOCAL_M * $GLOBAL_N * 2)`:
+ # the script also requires `sudo -C ($FD_COUNT + 4)`
+ # so you need 'Defaults closefrom_override' in the
+ # sudoers file.
+
+ if [ $FD_COUNT -lt $(($NODE_COUNT * 2)) ]; then
+ echo "File descriptors do not match requirements!" >&2
+ exit 1
+ fi
+}
+
+netjail_check_bin() {
+ local PROGRAM=$1
+ local MATCH=$(ls $(echo $PATH | tr ":" "\n") | grep "^$PROGRAM\$" | tr "\n" " " | awk '{ print $1 }')
+
+ # quit if the required binary $PROGRAM can not be
+ # found in the used $PATH.
+
+ if [ "$MATCH" != "$PROGRAM" ]; then
+ echo "Required binary not found: $PROGRAM" >&2
+ exit 1
+ fi
+}
+
+netjail_bridge() {
+ netjail_next_interface
+ local NUM=$RESULT
+ local BRIDGE=$(printf "%06x-%08x" $PREFIX $NUM)
+
+ ip link add $BRIDGE type bridge
+ ip link set dev $BRIDGE up
+
+ RESULT=$BRIDGE
+}
+
+netjail_bridge_name() {
+ netjail_next_interface
+ local NUM=$RESULT
+ local BRIDGE=$(printf "%06x-%08x" $PREFIX $NUM)
+
+ RESULT=$BRIDGE
+}
+
+netjail_bridge_clear() {
+ local BRIDGE=$1
+
+ ip link delete $BRIDGE
+}
+
+netjail_node() {
+ netjail_next_namespace
+ local NUM=$RESULT
+ local NODE=$(printf "%06x-%08x" $PREFIX $NUM)
+
+ ip netns add $NODE
+
+ RESULT=$NODE
+}
+
+netjail_node_name() {
+ netjail_next_namespace
+ local NUM=$RESULT
+ local NODE=$(printf "%06x-%08x" $PREFIX $NUM)
+
+ RESULT=$NODE
+}
+
+netjail_node_clear() {
+ local NODE=$1
+
+ ip netns delete $NODE
+}
+
+netjail_node_link_bridge() {
+ local NODE=$1
+ local BRIDGE=$2
+ local ADDRESS=$3
+ local MASK=$4
+
+ netjail_next_interface
+ local NUM_IF=$RESULT
+ netjail_next_interface
+ local NUM_BR=$RESULT
+
+ local LINK_IF=$(printf "%06x-%08x" $PREFIX $NUM_IF)
+ local LINK_BR=$(printf "%06x-%08x" $PREFIX $NUM_BR)
+
+ ip link add $LINK_IF type veth peer name $LINK_BR
+ ip link set $LINK_IF netns $NODE
+ ip link set $LINK_BR master $BRIDGE
+
+ ip -n $NODE addr add "$ADDRESS/$MASK" dev $LINK_IF
+ ip -n $NODE link set $LINK_IF up
+ ip -n $NODE link set up dev lo
+
+ ip link set $LINK_BR up
+
+ RESULT=$LINK_BR
+}
+
+netjail_node_link_bridge_name() {
+
+ netjail_next_interface
+ netjail_next_interface
+ local NUM_BR=$RESULT
+
+ local LINK_BR=$(printf "%06x-%08x" $PREFIX $NUM_BR)
+
+ RESULT=$LINK_BR
+}
+
+netjail_node_unlink_bridge() {
+ local LINK_BR=$1
+
+ ip link delete $LINK_BR
+}
+
+netjail_node_add_nat() {
+ local NODE=$1
+ local ADDRESS=$2
+ local MASK=$3
+
+ ip netns exec $NODE iptables -t nat -A POSTROUTING -s "$ADDRESS/$MASK" -j MASQUERADE
+}
+
+netjail_node_add_default() {
+ local NODE=$1
+ local ADDRESS=$2
+
+ ip -n $NODE route add default via $ADDRESS
+}
+
+netjail_node_exec() {
+ JAILOR=${SUDO_USER:?must run in sudo}
+ local NODE=$1
+ local FD_IN=$2
+ local FD_OUT=$3
+ shift 3
+
+ ip netns exec $NODE sudo -u $JAILOR -- $@ 1>& $FD_OUT 0<& $FD_IN
+}
+
+netjail_node_exec_without_fds() {
+ JAILOR=${SUDO_USER:?must run in sudo}
+ NODE=$1
+ shift 1
+
+ ip netns exec $NODE sudo -u $JAILOR -- $@
+}
+
+netjail_node_exec_without_fds_and_sudo() {
+ NODE=$1
+ shift 1
+
+ ip netns exec $NODE $@
+}
+
+netjail_kill() {
+ local PID=$1
+ local MATCH=$(ps --pid $PID | awk "{ if ( \$1 == $PID ) { print \$1 } }" | wc -l)
+
+ if [ $MATCH -gt 0 ]; then
+ kill -n 19 $PID
+
+ for CHILD in $(ps -o pid,ppid -ax | awk "{ if ( \$2 == $PID ) { print \$1 } }"); do
+ netjail_kill $CHILD
+ done
+
+ kill $PID
+ fi
+}
+
+netjail_killall() {
+ if [ $# -gt 0 ]; then
+ local PIDS=$1
+
+ for PID in $PIDS; do
+ netjail_kill $PID
+ done
+ fi
+}
+
+netjail_waitall() {
+ if [ $# -gt 0 ]; then
+ local PIDS=$1
+
+ for PID in $PIDS; do
+ wait $PID
+ done
+ fi
+}
+
diff --git a/src/testing/netjail_exec_v2.sh b/src/testing/netjail_exec_v2.sh
new file mode 100755
index 000000000..597baad20
--- /dev/null
+++ b/src/testing/netjail_exec_v2.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+. "./../testing/netjail_core_v2.sh"
+
+set -eu
+set -x
+
+export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
+
+M=$1
+N=$2
+
+NODE=$6
+
+netjail_node_exec_without_fds_and_sudo $NODE $3 $4 $5 $1 $2
diff --git a/src/testing/netjail_start_v2.sh b/src/testing/netjail_start_v2.sh
new file mode 100755
index 000000000..cf1fe113a
--- /dev/null
+++ b/src/testing/netjail_start_v2.sh
@@ -0,0 +1,61 @@
+#!/bin/bash
+. "./../testing/netjail_core_v2.sh"
+. "./../testing/topo.sh"
+
+set -eu
+set -x
+
+export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
+
+filename=$1
+PREFIX=$2
+
+read_topology $filename
+
+shift 2
+
+LOCAL_GROUP="192.168.15"
+GLOBAL_GROUP="92.68.150"
+KNOWN_GROUP="92.68.151"
+
+
+echo "Start [local: $LOCAL_GROUP.0/24, global: $GLOBAL_GROUP.0/16]"
+
+netjail_bridge
+NETWORK_NET=$RESULT
+
+for X in $(seq $KNOWN); do
+ netjail_node
+ KNOWN_NODES[$X]=$RESULT
+ netjail_node_link_bridge ${KNOWN_NODES[$X]} $NETWORK_NET "$KNOWN_GROUP.$X" 16
+ KNOWN_LINKS[$X]=$RESULT
+done
+
+declare -A NODES
+declare -A NODE_LINKS
+
+for N in $(seq $GLOBAL_N); do
+ netjail_node
+ ROUTERS[$N]=$RESULT
+ netjail_node_link_bridge ${ROUTERS[$N]} $NETWORK_NET "$GLOBAL_GROUP.$N" 16
+ NETWORK_LINKS[$N]=$RESULT
+ netjail_bridge
+ ROUTER_NETS[$N]=$RESULT
+
+ for M in $(seq $LOCAL_M); do
+ netjail_node
+ NODES[$N,$M]=$RESULT
+ netjail_node_link_bridge ${NODES[$N,$M]} ${ROUTER_NETS[$N]} "$LOCAL_GROUP.$M" 24
+ NODE_LINKS[$N,$M]=$RESULT
+ done
+
+ ROUTER_ADDR="$LOCAL_GROUP.$(($LOCAL_M+1))"
+ netjail_node_link_bridge ${ROUTERS[$N]} ${ROUTER_NETS[$N]} $ROUTER_ADDR 24
+ ROUTER_LINKS[$N]=$RESULT
+
+ netjail_node_add_nat ${ROUTERS[$N]} $ROUTER_ADDR 24
+
+ for M in $(seq $LOCAL_M); do
+ netjail_node_add_default ${NODES[$N,$M]} $ROUTER_ADDR
+ done
+done
diff --git a/src/testing/netjail_stop_v2.sh b/src/testing/netjail_stop_v2.sh
new file mode 100755
index 000000000..6e9fd1ccc
--- /dev/null
+++ b/src/testing/netjail_stop_v2.sh
@@ -0,0 +1,59 @@
+#!/bin/bash
+. "./../testing/netjail_core_v2.sh"
+. "./../testing/topo.sh"
+
+set -eu
+set -x
+
+export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
+
+filename=$1
+PREFIX=$2
+
+read_topology $filename
+
+declare -A NODES
+declare -A NODE_LINKS
+
+netjail_bridge_name
+NETWORK_NET=$RESULT
+
+for X in $(seq $KNOWN); do
+ netjail_node_name
+ KNOWN_NODES[$X]=$RESULT
+ netjail_node_link_bridge_name
+ KNOWN_LINKS[$X]=$RESULT
+ netjail_node_unlink_bridge ${KNOWN_LINKS[$X]}
+ netjail_node_clear ${KNOWN_NODES[$X]}
+done
+
+for N in $(seq $GLOBAL_N); do
+ netjail_node_name
+ ROUTERS[$N]=$RESULT
+ netjail_node_link_bridge_name
+ NETWORK_LINKS[$N]=$RESULT
+ netjail_bridge_name
+ ROUTER_NETS[$N]=$RESULT
+ netjail_node_link_bridge_name
+ ROUTER_LINKS[$N]=$RESULT
+
+ netjail_node_unlink_bridge ${ROUTER_LINKS[$N]}
+
+ for M in $(seq $LOCAL_M); do
+ netjail_node_name
+ NODES[$N,$M]=$RESULT
+ netjail_node_link_bridge_name
+ NODE_LINKS[$N,$M]=$RESULT
+ netjail_node_unlink_bridge ${NODE_LINKS[$N,$M]}
+ netjail_node_clear ${NODES[$N,$M]}
+ done
+
+
+ netjail_bridge_clear ${ROUTER_NETS[$N]}
+ netjail_node_unlink_bridge ${NETWORK_LINKS[$N]}
+ netjail_node_clear ${ROUTERS[$N]}
+done
+
+netjail_bridge_clear $NETWORK_NET
+
+echo "Done"
diff --git a/src/testing/test_testing_api_cmd_netjail.c b/src/testing/test_testing_api_cmd_netjail.c
index 543642109..aeddfb7c9 100644
--- a/src/testing/test_testing_api_cmd_netjail.c
+++ b/src/testing/test_testing_api_cmd_netjail.c
@@ -29,6 +29,13 @@
/**
+ * Return value of the test.
+ *
+ */
+static unsigned int rv = 0;
+
+
+/**
* Main function to run the test cases.
*
* @param cls not used.
@@ -44,7 +51,8 @@ run (void *cls)
GNUNET_TESTING_cmd_netjail_start_testing_system ("netjail-start-testbed-1",
"2",
"2",
- "libgnunet_plugin_testcmd"),
+ "libgnunet_plugin_testcmd",
+ &rv),
GNUNET_TESTING_cmd_stop_testing_system ("stop-testbed",
"netjail-start-testbed-1",
"2",
diff --git a/src/testing/testing.c b/src/testing/testing.c
index 991c11a6c..fcde39901 100644
--- a/src/testing/testing.c
+++ b/src/testing/testing.c
@@ -33,6 +33,7 @@
#include "gnunet_util_lib.h"
#include "gnunet_arm_service.h"
#include "gnunet_testing_lib.h"
+#include "gnunet_testing_ng_lib.h"
#define LOG(kind, ...) GNUNET_log_from (kind, "testing-api", __VA_ARGS__)
@@ -1308,7 +1309,7 @@ GNUNET_TESTING_peer_configure (struct GNUNET_TESTING_System *system,
peer->nports = nports;
return peer;
-err_ret:
+ err_ret:
GNUNET_free (ss_instances);
GNUNET_free (ports);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s", emsg_);
@@ -1773,4 +1774,382 @@ GNUNET_TESTING_get_testname_from_underscore (const char *argv0)
}
+static unsigned int
+get_first_value (char *line)
+{
+ char *copy;
+ size_t slen;
+ char *token;
+ unsigned int ret;
+ char *rest = NULL;
+
+ slen = strlen (line) + 1;
+ copy = malloc (slen);
+ memcpy (copy, line, slen);
+ token = strtok_r (copy, ":", &rest);
+ token = strtok_r (NULL, ":", &rest);
+ sscanf (token, "%u", &ret);
+ free (copy);
+ return ret;
+}
+
+
+static char *
+get_key (char *line)
+{
+ char *copy;
+ size_t slen;
+ char *token;
+ char *ret;
+ char *rest = NULL;
+
+ slen = strlen (line) + 1;
+ copy = malloc (slen);
+ memcpy (copy, line, slen);
+ token = strtok_r (copy, ":", &rest);
+ ret = malloc (2);
+ memcpy (ret, token, 2);
+ free (copy);
+ return ret;
+}
+
+
+static char *
+get_first_string_value (char *line)
+{
+ char *copy;
+ size_t slen, slen_token;
+ char *token;
+ char *ret;
+ char *rest = NULL;
+
+ slen = strlen (line) + 1;
+ copy = malloc (slen);
+ memcpy (copy, line, slen);
+ token = strtok_r (copy, ":", &rest);
+ token = strtok_r (NULL, ":", &rest);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "first token %s\n",
+ token);
+ slen_token = strlen (token);
+ ret = malloc (slen_token + 1);
+ memcpy (ret, token, slen_token + 1);
+ free (copy);
+ return ret;
+}
+
+
+static unsigned int
+get_second_value (char *line)
+{
+ char *copy;
+ size_t slen;
+ char *token;
+ unsigned int ret;
+ char *rest = NULL;
+
+ slen = strlen (line) + 1;
+ copy = malloc (slen);
+ memcpy (copy, line, slen);
+ token = strtok_r (copy, ":", &rest);
+ token = strtok_r (NULL, ":", &rest);
+ token = strtok_r (NULL, ":", &rest);
+ sscanf (token, "%u", &ret);
+ free (copy);
+ return ret;
+}
+
+
+static char *
+get_value (char *key, char *line)
+{
+ char *copy;
+ size_t slen, slen_token;
+ char *token;
+ char *token2;
+ char *temp;
+ char *rest = NULL;
+ char *ret;
+
+ slen = strlen (line) + 1;
+ copy = malloc (slen);
+ memcpy (copy, line, slen);
+ temp = strstr (copy, key);
+ if (NULL == temp)
+ return NULL;
+ token = strtok_r (temp, ":", &rest);
+ token = strtok_r (NULL, ":", &rest);
+ token2 = strtok_r (token, "}", &rest);
+ slen_token = strlen (token2);
+ ret = malloc (slen_token + 1);
+ memcpy (ret, token2, slen_token + 1);
+ free (copy);
+ return ret;
+}
+
+
+/**
+ * Getting the topology from file.
+ *
+ * @param filename The name of the topology file.
+ * @return The GNUNET_TESTING_NetjailTopology
+ */
+struct GNUNET_TESTING_NetjailTopology *
+GNUNET_TESTING_get_topo_from_file (const char *filename)
+{
+ uint64_t fs;
+ char *data;
+ char *token;
+ char *key;
+ unsigned int out;
+ char *rest = NULL;
+ char *value;
+ int ret;
+ struct GNUNET_TESTING_NetjailTopology *topo = GNUNET_new (struct
+ GNUNET_TESTING_NetjailTopology);
+ struct GNUNET_TESTING_NetjailNode *node;
+ struct GNUNET_TESTING_NetjailRouter *router;
+ struct GNUNET_TESTING_NetjailNamespace *namespace;
+ struct GNUNET_ShortHashCode *hkey;
+ struct GNUNET_HashCode hc;
+ topo->map_namespaces =
+ GNUNET_CONTAINER_multishortmap_create (1,GNUNET_NO);
+ topo->map_globals =
+ GNUNET_CONTAINER_multishortmap_create (1,GNUNET_NO);
+
+ if (GNUNET_YES != GNUNET_DISK_file_test (filename))
+ {
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ _ ("Topology file %s not found\n"),
+ filename);
+ return NULL;
+ }
+ if (GNUNET_OK !=
+ GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES))
+ {
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ _ ("Topology file %s has no data\n"),
+ filename);
+ return NULL;
+ }
+ data = GNUNET_malloc (fs);
+ if (fs != GNUNET_DISK_fn_read (filename, data, fs))
+ {
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ _ ("Topology file %s cannot be read\n"),
+ filename);
+ GNUNET_free (data);
+ return NULL;
+ }
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "data: %s\n",
+ data);
+
+ token = strtok_r (data, "\n", &rest);
+
+ while (NULL != token)
+ {
+ key = get_key (token);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "In the loop with token: %s beginning with %s\n",
+ token,
+ key);
+ if (0 == strcmp (key, "M"))
+ {
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Get first Value for M.\n");
+ out = get_first_value (token);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "M: %u\n",
+ out);
+ topo->nodes_m = out;
+ }
+ else if (0 == strcmp (key, "N"))
+ {
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Get first Value for N.\n");
+ out = get_first_value (token);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "N: %u\n",
+ out);
+ topo->namespaces_n = out;
+ }
+ else if (0 == strcmp (key, "X"))
+ {
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Get first Value for X.\n");
+ out = get_first_value (token);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "X: %u\n",
+ out);
+ topo->nodes_x = out;
+ }
+ else if (0 == strcmp (key, "T"))
+ {
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Get first string value for T.\n");
+ value = get_first_string_value (token);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "value: %s\n",
+ value);
+ topo->plugin = value;
+ }
+ else if (0 == strcmp (key, "K"))
+ {
+ hkey = GNUNET_new (struct GNUNET_ShortHashCode);
+ node = GNUNET_new (struct GNUNET_TESTING_NetjailNode);
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Get first Value for K.\n");
+ out = get_first_value (token);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "K: %u\n",
+ out);
+ node->node_n = out;
+ GNUNET_CRYPTO_hash (&out, sizeof(out), &hc);
+ memcpy (hkey,
+ &hc,
+ sizeof (*hkey));
+ node->is_global = GNUNET_YES;
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Get value for key value on K.\n");
+ value = get_value ("plugin", token);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "value: %s\n",
+ value);
+ if (0 == GNUNET_CONTAINER_multishortmap_contains (topo->map_globals,
+ hkey))
+ GNUNET_break (0);
+ else
+ GNUNET_CONTAINER_multishortmap_put (topo->map_globals,
+ hkey,
+ node,
+ GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
+ }
+ else if (0 == strcmp (key, "R"))
+ {
+ hkey = GNUNET_new (struct GNUNET_ShortHashCode);
+ router = GNUNET_new (struct GNUNET_TESTING_NetjailRouter);
+ node = GNUNET_new (struct GNUNET_TESTING_NetjailNode);
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Get first Value for R.\n");
+ out = get_first_value (token);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "R: %u\n",
+ out);
+ node->node_n = out;
+ GNUNET_CRYPTO_hash (&out, sizeof(out), &hc);
+ memcpy (hkey,
+ &hc,
+ sizeof (*hkey));
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Get value for key tcp_port on R.\n");
+ value = get_value ("tcp_port", token);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "tcp_port: %s\n",
+ value);
+ ret = sscanf (value, "%u", &(router->tcp_port));
+
+ GNUNET_break (0 == ret || 1 < router->tcp_port);
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Get value for key udp_port on R.\n");
+ value = get_value ("udp_port", token);
+ ret = sscanf (value, "%u", &(router->udp_port));
+ GNUNET_break (0 == ret || 1 < router->udp_port);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "udp_port: %s\n",
+ value);
+
+ if (0 == GNUNET_CONTAINER_multishortmap_contains (topo->map_namespaces,
+ hkey))
+ {
+ namespace = GNUNET_CONTAINER_multishortmap_get (topo->map_namespaces,
+ hkey);
+ }
+ else
+ {
+ namespace = GNUNET_new (struct GNUNET_TESTING_NetjailNamespace);
+ namespace->namespace_n = out;
+ GNUNET_CONTAINER_multishortmap_put (topo->map_namespaces,
+ hkey,
+ namespace,
+ GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
+ }
+ namespace->router = router;
+
+ }
+ else if (0 == strcmp (key, "P"))
+ {
+ hkey = GNUNET_new (struct GNUNET_ShortHashCode);
+ node = GNUNET_new (struct GNUNET_TESTING_NetjailNode);
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Get first Value for P.\n");
+ out = get_first_value (token);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "P: %u\n",
+ out);
+ GNUNET_CRYPTO_hash (&out, sizeof(out), &hc);
+ memcpy (hkey,
+ &hc,
+ sizeof (*hkey));
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Get value for key plugin on P.\n");
+ value = get_value ("plugin", token);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "plugin: %s\n",
+ value);
+ if (0 == GNUNET_CONTAINER_multishortmap_contains (topo->map_namespaces,
+ hkey))
+ {
+ namespace = GNUNET_CONTAINER_multishortmap_get (topo->map_namespaces,
+ hkey);
+ }
+ else
+ {
+ namespace = GNUNET_new (struct GNUNET_TESTING_NetjailNamespace);
+ namespace->namespace_n = out;
+ GNUNET_CONTAINER_multishortmap_put (topo->map_namespaces,
+ hkey,
+ namespace,
+ GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
+ }
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Get second Value for P.\n");
+ out = get_second_value (token);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "P: %u\n",
+ out);
+ GNUNET_CRYPTO_hash (&out, sizeof(out), &hc);
+ memcpy (hkey,
+ &hc,
+ sizeof (*hkey));
+ if (0 == GNUNET_CONTAINER_multishortmap_contains (namespace->nodes,
+ hkey))
+ {
+ GNUNET_break (0);
+ }
+ else
+ {
+ node = GNUNET_new (struct GNUNET_TESTING_NetjailNode);
+ GNUNET_CONTAINER_multishortmap_put (namespace->nodes,
+ hkey,
+ node,
+ GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
+ node->plugin = value;
+ node->node_n = out;
+ node->namespace_n = namespace->namespace_n;
+ }
+ }
+ token = strtok_r (NULL, "\n", &rest);
+ }
+
+ return topo;
+}
+
+
/* end of testing.c */
diff --git a/src/testing/testing_api_cmd_netjail_start_testsystem.c b/src/testing/testing_api_cmd_netjail_start_testsystem.c
index 0fe0541b0..531621eb5 100644
--- a/src/testing/testing_api_cmd_netjail_start_testsystem.c
+++ b/src/testing/testing_api_cmd_netjail_start_testsystem.c
@@ -278,26 +278,6 @@ GNUNET_TESTING_get_trait_helper_handles (const struct
/**
- * Offer messages received via testing cmd helper from trait
- *
- * @param cmd command to extract the message from.
- * @param pt pointer to message.
- * @return #GNUNET_OK on success.
- */
-int
-GNUNET_TESTING_get_trait_helper_messages (const struct
- GNUNET_TESTING_Command *cmd,
- struct HelperMessage ***
- hp_messages_head)
-{
- return cmd->traits (cmd->cls,
- (const void **) hp_messages_head,
- "hp_msgs_head",
- (unsigned int) 1);
-}
-
-
-/**
* Continuation function from GNUNET_HELPER_send()
*
* @param cls closure
diff --git a/src/testing/testing_api_cmd_netjail_start_testsystem_v2.c b/src/testing/testing_api_cmd_netjail_start_testsystem_v2.c
new file mode 100644
index 000000000..64ce549a4
--- /dev/null
+++ b/src/testing/testing_api_cmd_netjail_start_testsystem_v2.c
@@ -0,0 +1,718 @@
+/*
+ This file is part of GNUnet
+ Copyright (C) 2021 GNUnet e.V.
+
+ GNUnet is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License,
+ or (at your option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ SPDX-License-Identifier: AGPL3.0-or-later
+ */
+
+/**
+ * @file testing/testing_api_cmd_hello_world.c
+ * @brief Command to start the netjail peers.
+ * @author t3sserakt
+ */
+#include "platform.h"
+#include "gnunet_testing_ng_lib.h"
+#include "testing_cmds.h"
+
+#define NETJAIL_EXEC_SCRIPT "./../testing/netjail_exec_v2.sh"
+
+/**
+ * Struct to store messages send/received by the helper into a DLL
+ *
+ */
+struct HelperMessage
+{
+
+ /**
+ * Kept in a DLL.
+ */
+ struct HelperMessage *next;
+
+ /**
+ * Kept in a DLL.
+ */
+ struct HelperMessage *prev;
+
+ /**
+ * Size of the original message.
+ */
+ uint16_t bytes_msg;
+
+ /* Followed by @e bytes_msg of msg.*/
+};
+
+
+/**
+ * Struct to store information handed over to callbacks.
+ *
+ */
+struct NetJailState
+{
+ /**
+ * The complete topology infomation.
+ */
+ struct GNUNET_TESTING_NetjailTopology *topology;
+
+ /**
+ * Pointer to the return value of the test.
+ *
+ */
+ unsigned int *rv;
+
+ /**
+ * Head of the DLL which stores messages received by the helper.
+ *
+ */
+ struct HelperMessage *hp_messages_head;
+
+ /**
+ * Tail of the DLL which stores messages received by the helper.
+ *
+ */
+ struct HelperMessage *hp_messages_tail;
+
+ /**
+ * Array with handles of helper processes.
+ */
+ struct GNUNET_HELPER_Handle **helper;
+
+ /**
+ * Size of the array NetJailState#helper.
+ *
+ */
+ unsigned int n_helper;
+
+ /**
+ * Number of nodes in a natted subnet.
+ *
+ */
+ unsigned int local_m;
+
+ /**
+ * Number of natted subnets.
+ *
+ */
+ unsigned int global_n;
+
+ /**
+ * Number of global known nodes.
+ *
+ */
+ unsigned int known;
+
+ /**
+ * The send handle for the helper
+ */
+ struct GNUNET_HELPER_SendHandle **shandle;
+
+ /**
+ * Size of the array NetJailState#shandle.
+ *
+ */
+ unsigned int n_shandle;
+
+ /**
+ * The messages send to the helper.
+ */
+ struct GNUNET_MessageHeader **msg;
+
+ /**
+ * Size of the array NetJailState#msg.
+ *
+ */
+ unsigned int n_msg;
+
+ /**
+ * Number of test environments started.
+ *
+ */
+ unsigned int number_of_testsystems_started;
+
+ /**
+ * Number of peers started.
+ *
+ */
+ unsigned int number_of_peers_started;
+
+ /**
+ * Number of local tests finished.
+ *
+ */
+ unsigned int number_of_local_test_finished;
+
+ /**
+ * Name of the test case plugin the helper will load.
+ *
+ */
+ char *plugin_name;
+
+ /**
+ * HEAD of the DLL containing TestingSystemCount.
+ *
+ */
+ struct TestingSystemCount *tbcs_head;
+
+ /**
+ * TAIL of the DLL containing TestingSystemCount.
+ *
+ */
+ struct TestingSystemCount *tbcs_tail;
+};
+
+/**
+ * Struct containing the number of the test environment and the NetJailState which
+ * will be handed to callbacks specific to a test environment.
+ */
+struct TestingSystemCount
+{
+ /**
+ * Kept in a DLL.
+ */
+ struct TestingSystemCount *next;
+
+ /**
+ * Kept in a DLL.
+ */
+ struct TestingSystemCount *prev;
+
+ /**
+ * The number of the test environment.
+ *
+ */
+ unsigned int count;
+
+ /**
+ * Struct to store information handed over to callbacks.
+ *
+ */
+ struct NetJailState *ns;
+};
+
+/**
+* Code to clean up resource this cmd used.
+*
+* @param cls closure
+* @param cmd current CMD being cleaned up.
+*/
+static void
+netjail_exec_cleanup (void *cls,
+ const struct GNUNET_TESTING_Command *cmd)
+{
+ struct NetJailState *ns = cls;
+ struct HelperMessage *message_pos;
+ struct TestingSystemCount *tbc_pos;
+
+ while (NULL != (message_pos = ns->hp_messages_head))
+ {
+ GNUNET_CONTAINER_DLL_remove (ns->hp_messages_head,
+ ns->hp_messages_tail,
+ message_pos);
+ GNUNET_free (message_pos);
+ }
+ while (NULL != (tbc_pos = ns->tbcs_head))
+ {
+ GNUNET_CONTAINER_DLL_remove (ns->tbcs_head,
+ ns->tbcs_tail,
+ tbc_pos);
+ GNUNET_free (tbc_pos);
+ }
+ GNUNET_free (ns);
+}
+
+
+/**
+ * This function prepares an array with traits.
+ *
+ */
+static int
+netjail_exec_traits (void *cls,
+ const void **ret,
+ const char *trait,
+ unsigned int index)
+{
+ struct NetJailState *ns = cls;
+ struct GNUNET_HELPER_Handle **helper = ns->helper;
+ struct HelperMessage *hp_messages_head = ns->hp_messages_head;
+
+
+ struct GNUNET_TESTING_Trait traits[] = {
+ {
+ .index = 0,
+ .trait_name = "helper_handles",
+ .ptr = (const void *) helper,
+ },
+ {
+ .index = 1,
+ .trait_name = "hp_msgs_head",
+ .ptr = (const void *) hp_messages_head,
+ },
+ GNUNET_TESTING_trait_end ()
+ };
+
+ return GNUNET_TESTING_get_trait (traits,
+ ret,
+ trait,
+ index);
+}
+
+
+/**
+ * Offer handles to testing cmd helper from trait
+ *
+ * @param cmd command to extract the message from.
+ * @param pt pointer to message.
+ * @return #GNUNET_OK on success.
+ */
+int
+GNUNET_TESTING_get_trait_helper_handles_v2 (const struct
+ GNUNET_TESTING_Command *cmd,
+ struct GNUNET_HELPER_Handle ***
+ helper)
+{
+ return cmd->traits (cmd->cls,
+ (const void **) helper,
+ "helper_handles",
+ (unsigned int) 0);
+}
+
+
+/**
+ * Continuation function from GNUNET_HELPER_send()
+ *
+ * @param cls closure
+ * @param result GNUNET_OK on success,
+ * GNUNET_NO if helper process died
+ * GNUNET_SYSERR during GNUNET_HELPER_stop
+ */
+static void
+clear_msg (void *cls, int result)
+{
+ struct TestingSystemCount *tbc = cls;
+ struct NetJailState *ns = tbc->ns;
+
+ GNUNET_assert (NULL != ns->shandle[tbc->count - 1]);
+ ns->shandle[tbc->count - 1] = NULL;
+ GNUNET_free (ns->msg[tbc->count - 1]);
+ ns->msg[tbc->count - 1] = NULL;
+}
+
+
+/**
+ * Functions with this signature are called whenever a
+ * complete message is received by the tokenizer.
+ *
+ * Do not call GNUNET_SERVER_mst_destroy in callback
+ *
+ * @param cls closure
+ * @param client identification of the client
+ * @param message the actual message
+ *
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR to stop further processing
+ */
+static int
+helper_mst (void *cls, const struct GNUNET_MessageHeader *message)
+{
+ struct TestingSystemCount *tbc = cls;
+ struct NetJailState *ns = tbc->ns;
+ struct HelperMessage *hp_msg;
+
+ if (GNUNET_MESSAGE_TYPE_CMDS_HELPER_REPLY == ntohs (message->type))
+ {
+ ns->number_of_testsystems_started++;
+ }
+ else if (GNUNET_MESSAGE_TYPE_CMDS_HELPER_PEER_STARTED == ntohs (
+ message->type))
+ {
+ ns->number_of_peers_started++;
+ }
+ else if (GNUNET_MESSAGE_TYPE_CMDS_HELPER_LOCAL_FINISHED == ntohs (
+ message->type))
+ {
+ ns->number_of_local_test_finished++;
+ }
+ else
+ {
+ hp_msg = GNUNET_new (struct HelperMessage);
+ hp_msg->bytes_msg = message->size;
+ memcpy (&hp_msg[1], message, message->size);
+ GNUNET_CONTAINER_DLL_insert (ns->hp_messages_head, ns->hp_messages_tail,
+ hp_msg);
+ }
+
+ return GNUNET_OK;
+}
+
+
+/**
+ * Callback called if there was an exception during execution of the helper.
+ *
+ */
+static void
+exp_cb (void *cls)
+{
+ struct NetJailState *ns = cls;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Called exp_cb.\n");
+ *ns->rv = 1;
+}
+
+
+/**
+ * Function to initialize a init message for the helper.
+ *
+ * @param m_char The actual node in a namespace. //TODO Change this to unsigned int
+ * @param n_char The actual namespace. //TODO Change this to unsigned int
+ * @param plugin_name Name of the test case plugin the helper will load.
+ *
+ */
+static struct GNUNET_CMDS_HelperInit *
+create_helper_init_msg_ (const char *plugin_name)
+{
+ struct GNUNET_CMDS_HelperInit *msg;
+ uint16_t plugin_name_len;
+ uint16_t msg_size;
+
+ GNUNET_assert (NULL != plugin_name);
+ plugin_name_len = strlen (plugin_name);
+ msg_size = sizeof(struct GNUNET_CMDS_HelperInit) + plugin_name_len;
+ msg = GNUNET_malloc (msg_size);
+ msg->header.size = htons (msg_size);
+ msg->header.type = htons (GNUNET_MESSAGE_TYPE_CMDS_HELPER_INIT);
+ msg->plugin_name_size = htons (plugin_name_len);
+ GNUNET_memcpy ((char *) &msg[1],
+ plugin_name,
+ plugin_name_len);
+ return msg;
+}
+
+
+/**
+ * Function which start a single helper process.
+ *
+ */
+static void
+start_helper (struct NetJailState *ns, struct
+ GNUNET_CONFIGURATION_Handle *config,
+ unsigned int m,
+ unsigned int n)
+{
+ struct GNUNET_HELPER_Handle *helper;
+ struct GNUNET_CMDS_HelperInit *msg;
+ struct TestingSystemCount *tbc;
+ char *m_char, *n_char, *global_n_char, *local_m_char, *known_char, *node_id,
+ *plugin;
+ pid_t pid;
+ unsigned int script_num;
+ struct GNUNET_ShortHashCode *hkey;
+ struct GNUNET_HashCode hc;
+ struct GNUNET_TESTING_NetjailTopology *topology = ns->topology;
+ struct GNUNET_TESTING_NetjailNode *node;
+ struct GNUNET_TESTING_NetjailNamespace *namespace;
+
+
+ if (0 == m)
+ script_num = n - 1;
+ else
+ script_num = n - 1 + (n - 1) * ns->local_m + m + ns->known;
+ pid = getpid ();
+
+ GNUNET_asprintf (&m_char, "%u", m);
+ GNUNET_asprintf (&n_char, "%u", n);
+ GNUNET_asprintf (&local_m_char, "%u", ns->local_m);
+ GNUNET_asprintf (&global_n_char, "%u",ns->global_n);
+ GNUNET_asprintf (&known_char, "%u",ns->known);
+ GNUNET_asprintf (&node_id, "%06x-%08x\n",
+ pid,
+ script_num);
+
+
+ char *const script_argv[] = {NETJAIL_EXEC_SCRIPT,
+ m_char,
+ n_char,
+ GNUNET_OS_get_libexec_binary_path (
+ HELPER_CMDS_BINARY),
+ global_n_char,
+ local_m_char,
+ node_id,
+ NULL};
+
+ unsigned int helper_check = GNUNET_OS_check_helper_binary (
+ NETJAIL_EXEC_SCRIPT,
+ GNUNET_YES,
+ NULL);
+
+ tbc = GNUNET_new (struct TestingSystemCount);
+ tbc->ns = ns;
+ if (0 == m)
+ tbc->count = n;
+ else
+ tbc->count = (n - 1) * ns->local_m + m + ns->known;
+
+ GNUNET_CONTAINER_DLL_insert (ns->tbcs_head, ns->tbcs_tail,
+ tbc);
+
+
+ if (GNUNET_NO == helper_check)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "No SUID for %s!\n",
+ NETJAIL_EXEC_SCRIPT);
+ *ns->rv = 1;
+ }
+ else if (GNUNET_NO == helper_check)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "%s not found!\n",
+ NETJAIL_EXEC_SCRIPT);
+ *ns->rv = 1;
+ }
+
+ GNUNET_array_append (ns->helper, ns->n_helper, GNUNET_HELPER_start (
+ GNUNET_YES,
+ NETJAIL_EXEC_SCRIPT,
+ script_argv,
+ &helper_mst,
+ &exp_cb,
+ tbc));
+
+ helper = ns->helper[tbc->count - 1];
+
+ hkey = GNUNET_new (struct GNUNET_ShortHashCode);
+
+ plugin = ns->plugin_name;
+
+ if (0 == m)
+ {
+
+ GNUNET_CRYPTO_hash (&n, sizeof(n), &hc);
+ memcpy (hkey,
+ &hc,
+ sizeof (*hkey));
+ if (1 == GNUNET_CONTAINER_multishortmap_contains (topology->map_globals,
+ hkey))
+ {
+ node = GNUNET_CONTAINER_multishortmap_get (topology->map_globals,
+ hkey);
+ plugin = node->plugin;
+ }
+
+ }
+ else
+ {
+ GNUNET_CRYPTO_hash (&m, sizeof(m), &hc);
+ memcpy (hkey,
+ &hc,
+ sizeof (*hkey));
+ if (1 == GNUNET_CONTAINER_multishortmap_contains (topology->map_namespaces,
+ hkey))
+ {
+ namespace = GNUNET_CONTAINER_multishortmap_get (topology->map_namespaces,
+ hkey);
+ GNUNET_CRYPTO_hash (&n, sizeof(n), &hc);
+ memcpy (hkey,
+ &hc,
+ sizeof (*hkey));
+ if (1 == GNUNET_CONTAINER_multishortmap_contains (namespace->nodes,
+ hkey))
+ {
+ node = GNUNET_CONTAINER_multishortmap_get (namespace->nodes,
+ hkey);
+ plugin = node->plugin;
+ }
+ }
+
+
+ }
+
+ msg = create_helper_init_msg_ (plugin);
+
+ GNUNET_array_append (ns->msg, ns->n_msg, &msg->header);
+
+ GNUNET_array_append (ns->shandle, ns->n_shandle, GNUNET_HELPER_send (
+ helper,
+ &msg->header,
+ GNUNET_NO,
+ &clear_msg,
+ tbc));
+
+ if (NULL == ns->shandle[tbc->count - 1])
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Send handle is NULL!\n");
+ GNUNET_free (msg);
+ *ns->rv = 1;
+ }
+}
+
+
+/**
+* This function starts a helper process for each node.
+*
+* @param cls closure.
+* @param cmd CMD being run.
+* @param is interpreter state.
+*/
+static void
+netjail_exec_run (void *cls,
+ const struct GNUNET_TESTING_Command *cmd,
+ struct GNUNET_TESTING_Interpreter *is)
+{
+ struct NetJailState *ns = cls;
+ struct GNUNET_CONFIGURATION_Handle *config =
+ GNUNET_CONFIGURATION_create ();
+
+ for (int i = 1; i <= ns->known; i++)
+ {
+ start_helper (ns, config,
+ i,
+ 0);
+ }
+
+ for (int i = 1; i <= ns->global_n; i++)
+ {
+ for (int j = 1; j <= ns->local_m; j++)
+ {
+ start_helper (ns, config,
+ j,
+ i);
+ }
+ }
+}
+
+
+static void
+send_all_peers_started (unsigned int i, unsigned int j, struct NetJailState *ns)
+{
+ unsigned int total_number = ns->local_m * ns->global_n + ns->known;
+ struct GNUNET_CMDS_ALL_PEERS_STARTED *reply;
+ size_t msg_length;
+ struct GNUNET_HELPER_Handle *helper;
+ struct TestingSystemCount *tbc;
+
+ tbc = GNUNET_new (struct TestingSystemCount);
+ tbc->ns = ns;
+ // TODO This needs to be more generic. As we send more messages back and forth, we can not grow the arrays again and again, because this is to error prone.
+ if (0 == i)
+ tbc->count = j + total_number;
+ else
+ tbc->count = (i - 1) * ns->local_m + j + total_number + ns->known;
+
+ helper = ns->helper[tbc->count - 1 - total_number];
+ msg_length = sizeof(struct GNUNET_CMDS_ALL_PEERS_STARTED);
+ reply = GNUNET_new (struct GNUNET_CMDS_ALL_PEERS_STARTED);
+ reply->header.type = htons (
+ GNUNET_MESSAGE_TYPE_CMDS_HELPER_ALL_PEERS_STARTED);
+ reply->header.size = htons ((uint16_t) msg_length);
+
+ GNUNET_array_append (ns->msg, ns->n_msg, &reply->header);
+
+ struct GNUNET_HELPER_SendHandle *sh = GNUNET_HELPER_send (
+ helper,
+ &reply->header,
+ GNUNET_NO,
+ &clear_msg,
+ tbc);
+
+ GNUNET_array_append (ns->shandle, ns->n_shandle, sh);
+}
+
+
+/**
+ * This function checks on three different information.
+ *
+ * 1. Did all helpers start. This is only logged.
+ * 2. Did all peer start.
+ * In this case a GNUNET_MESSAGE_TYPE_CMDS_HELPER_ALL_PEERS_STARTED is send to all peers.
+ * 3. Did all peers finished the test case. In this case interpreter_next will be called.
+ *
+ */
+static int
+netjail_start_finish (void *cls,
+ GNUNET_SCHEDULER_TaskCallback cont,
+ void *cont_cls)
+{
+ unsigned int ret = GNUNET_NO;
+ struct NetJailState *ns = cls;
+ unsigned int total_number = ns->local_m * ns->global_n + ns->known;
+
+
+ if (ns->number_of_local_test_finished == total_number)
+ {
+ ret = GNUNET_YES;
+ cont (cont_cls);
+ }
+
+ if (ns->number_of_testsystems_started == total_number)
+ {
+ ns->number_of_testsystems_started = 0;
+ }
+
+ if (ns->number_of_peers_started == total_number)
+ {
+ for (int i = 1; i <= ns->known; i++)
+ {
+ send_all_peers_started (0,i, ns);
+ }
+
+ for (int i = 1; i <= ns->global_n; i++)
+ {
+ for (int j = 1; j <= ns->local_m; j++)
+ {
+ send_all_peers_started (i,j, ns);
+ }
+ }
+ ns->number_of_peers_started = 0;
+ }
+ return ret;
+}
+
+
+/**
+ * Create command.
+ *
+ * @param label Name for the command.
+ * @param topology_config Configuration file for the test topology.
+ * @param rv Pointer to the return value of the test.
+ * @return command.
+ */
+struct GNUNET_TESTING_Command
+GNUNET_TESTING_cmd_netjail_start_testing_system_v2 (const char *label,
+ const char *topology_config,
+ unsigned int *rv)
+{
+ struct NetJailState *ns;
+
+ struct GNUNET_TESTING_NetjailTopology *topology =
+ GNUNET_TESTING_get_topo_from_file (topology_config);
+
+ ns = GNUNET_new (struct NetJailState);
+ ns->rv = rv;
+ ns->local_m = topology->nodes_m;
+ ns->global_n = topology->namespaces_n;
+ ns->known = topology->nodes_x;
+ ns->plugin_name = topology->plugin;
+ ns->topology = topology;
+
+ struct GNUNET_TESTING_Command cmd = {
+ .cls = ns,
+ .label = label,
+ .run = &netjail_exec_run,
+ .finish = &netjail_start_finish,
+ .cleanup = &netjail_exec_cleanup,
+ .traits = &netjail_exec_traits
+ };
+
+ return cmd;
+}
diff --git a/src/testing/testing_api_cmd_netjail_start_v2.c b/src/testing/testing_api_cmd_netjail_start_v2.c
new file mode 100644
index 000000000..36fbb0e10
--- /dev/null
+++ b/src/testing/testing_api_cmd_netjail_start_v2.c
@@ -0,0 +1,229 @@
+/*
+ This file is part of GNUnet
+ Copyright (C) 2021 GNUnet e.V.
+
+ GNUnet is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License,
+ or (at your option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ SPDX-License-Identifier: AGPL3.0-or-later
+ */
+
+/**
+ * @file testing/testing_api_cmd_hello_world.c
+ * @brief Command to start the netjail script.
+ * @author t3sserakt
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_testing_ng_lib.h"
+
+#define NETJAIL_START_SCRIPT "./../testing/netjail_start_v2.sh"
+
+/**
+ * Struct to hold information for callbacks.
+ *
+ */
+struct NetJailState
+{
+ // Child Wait handle
+ struct GNUNET_ChildWaitHandle *cwh;
+
+ /**
+ * Configuration file for the test topology.
+ */
+ char *topology_config;
+
+ /**
+ * The process id of the start script.
+ */
+ struct GNUNET_OS_Process *start_proc;
+
+ // Flag indication if the script finished.
+ unsigned int finished;
+};
+
+
+/**
+ * The cleanup function of this cmd frees resources the cmd allocated.
+ *
+ */
+static void
+netjail_start_cleanup (void *cls,
+ const struct GNUNET_TESTING_Command *cmd)
+{
+ struct NetJailState *ns = cls;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "netjail_start_cleanup!\n");
+
+ if (NULL != ns->cwh)
+ {
+ GNUNET_wait_child_cancel (ns->cwh);
+ ns->cwh = NULL;
+ }
+ if (NULL != ns->start_proc)
+ {
+ GNUNET_assert (0 ==
+ GNUNET_OS_process_kill (ns->start_proc,
+ SIGKILL));
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_OS_process_wait (ns->start_proc));
+ GNUNET_OS_process_destroy (ns->start_proc);
+ ns->start_proc = NULL;
+ }
+ GNUNET_free (ns);
+}
+
+
+/**
+ * Trait function of this cmd does nothing.
+ *
+ */
+static int
+netjail_start_traits (void *cls,
+ const void **ret,
+ const char *trait,
+ unsigned int index)
+{
+ return GNUNET_OK;
+}
+
+
+/**
+ * Callback which will be called if the setup script finished.
+ *
+ */
+static void
+child_completed_callback (void *cls,
+ enum GNUNET_OS_ProcessStatusType type,
+ long unsigned int exit_code)
+{
+ struct NetJailState *ns = cls;
+
+ if (0 == exit_code)
+ {
+ ns->finished = GNUNET_YES;
+ }
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Child completed with an error!\n");
+ ns->finished = GNUNET_SYSERR;
+ }
+ GNUNET_OS_process_destroy (ns->start_proc);
+ ns->start_proc = NULL;
+}
+
+
+
+/**
+* The run method starts the script which setup the network namespaces.
+*
+* @param cls closure.
+* @param cmd CMD being run.
+* @param is interpreter state.
+*/
+static void
+netjail_start_run (void *cls,
+ const struct GNUNET_TESTING_Command *cmd,
+ struct GNUNET_TESTING_Interpreter *is)
+{
+ struct NetJailState *ns = cls;
+ char *pid;
+ GNUNET_asprintf (&pid,
+ "%u",
+ getpid ());
+ char *const script_argv[] = {NETJAIL_START_SCRIPT,
+ ns->topology_config,
+ pid,
+ NULL};
+ unsigned int helper_check = GNUNET_OS_check_helper_binary (
+ NETJAIL_START_SCRIPT,
+ GNUNET_YES,
+ NULL);
+
+ if (GNUNET_NO == helper_check)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "No SUID for %s!\n",
+ NETJAIL_START_SCRIPT);
+ GNUNET_TESTING_interpreter_fail ();
+ }
+ else if (GNUNET_NO == helper_check)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "%s not found!\n",
+ NETJAIL_START_SCRIPT);
+ GNUNET_TESTING_interpreter_fail ();
+ }
+
+ ns->start_proc = GNUNET_OS_start_process_vap (GNUNET_OS_INHERIT_STD_ERR,
+ NULL,
+ NULL,
+ NULL,
+ NETJAIL_START_SCRIPT,
+ script_argv);
+
+ ns->cwh = GNUNET_wait_child (ns->start_proc,
+ &child_completed_callback,
+ ns);
+ GNUNET_break (NULL != ns->cwh);
+}
+
+
+/**
+ * This function checks the flag NetJailState#finished, if this cmd finished.
+ *
+ */
+static int
+netjail_start_finish (void *cls,
+ GNUNET_SCHEDULER_TaskCallback cont,
+ void *cont_cls)
+{
+ struct NetJailState *ns = cls;
+
+ if (ns->finished)
+ {
+ cont (cont_cls);
+ }
+ return ns->finished;
+}
+
+/**
+ * Create command.
+ *
+ * @param label name for command.
+ * @param topology_config Configuration file for the test topology.
+ * @return command.
+ */
+struct GNUNET_TESTING_Command
+GNUNET_TESTING_cmd_netjail_start_v2 (const char *label,
+ char *topology_config)
+{
+ struct NetJailState *ns;
+
+ ns = GNUNET_new (struct NetJailState);
+ ns->finished = GNUNET_NO;
+ ns->topology_config = topology_config;
+
+ struct GNUNET_TESTING_Command cmd = {
+ .cls = ns,
+ .label = label,
+ .run = &netjail_start_run,
+ .finish = &netjail_start_finish,
+ .cleanup = &netjail_start_cleanup,
+ .traits = &netjail_start_traits
+ };
+
+ return cmd;
+}
diff --git a/src/testing/testing_api_cmd_netjail_stop_testsystem_v2.c b/src/testing/testing_api_cmd_netjail_stop_testsystem_v2.c
new file mode 100644
index 000000000..8eccc5764
--- /dev/null
+++ b/src/testing/testing_api_cmd_netjail_stop_testsystem_v2.c
@@ -0,0 +1,143 @@
+/*
+ This file is part of GNUnet
+ Copyright (C) 2021 GNUnet e.V.
+
+ GNUnet is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License,
+ or (at your option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ SPDX-License-Identifier: AGPL3.0-or-later
+ */
+
+/**
+ * @file testing/testing_api_cmd_hello_world.c
+ * @brief Command to start the netjail peers.
+ * @author t3sserakt
+ */
+#include "platform.h"
+#include "gnunet_testing_ng_lib.h"
+#include "testing_cmds.h"
+
+
+/**
+ * Struct to store information handed over to callbacks.
+ *
+ */
+struct StopHelperState
+{
+
+ const char *helper_start_label;
+
+ /**
+ * The process handle
+ */
+ struct GNUNET_HELPER_Handle **helper;
+
+ unsigned int local_m;
+
+ unsigned int global_n;
+};
+
+
+/**
+* Code to clean up resource this cmd used.
+*
+* @param cls closure
+* @param cmd current CMD being cleaned up.
+*/
+static void
+stop_testing_system_cleanup (void *cls,
+ const struct GNUNET_TESTING_Command *cmd)
+{
+
+}
+
+
+/**
+ * Trait function of this cmd does nothing.
+ *
+ */
+static int
+stop_testing_system_traits (void *cls,
+ const void **ret,
+ const char *trait,
+ unsigned int index)
+{
+ return GNUNET_OK;
+}
+
+
+/**
+* This function stops the helper process for each node.
+*
+* @param cls closure.
+* @param cmd CMD being run.
+* @param is interpreter state.
+*/
+static void
+stop_testing_system_run (void *cls,
+ const struct GNUNET_TESTING_Command *cmd,
+ struct GNUNET_TESTING_Interpreter *is)
+{
+ struct StopHelperState *shs = cls;
+ struct GNUNET_HELPER_Handle **helper;
+ const struct GNUNET_TESTING_Command *start_helper_cmd;
+
+ start_helper_cmd = GNUNET_TESTING_interpreter_lookup_command (
+ shs->helper_start_label);
+ GNUNET_TESTING_get_trait_helper_handles (start_helper_cmd,
+ &helper);
+
+ for (int i = 1; i <= shs->global_n; i++)
+ {
+ for (int j = 1; j <= shs->local_m; j++)
+ {
+ GNUNET_HELPER_stop (helper[(i - 1) * shs->local_m + j - 1],
+ GNUNET_YES);
+ }
+ }
+}
+
+
+/**
+ * Create command.
+ *
+ * @param label name for command.
+ * @param helper_start_label label of the cmd to start the test system.
+ * @param topology_config Configuration file for the test topology.
+ * @return command.
+ */
+struct GNUNET_TESTING_Command
+GNUNET_TESTING_cmd_stop_testing_system_v2 (const char *label,
+ const char *helper_start_label,
+ const char *topology_config)
+{
+ struct StopHelperState *shs;
+
+ struct GNUNET_TESTING_NetjailTopology *topology =
+ GNUNET_TESTING_get_topo_from_file (topology_config);
+
+ shs = GNUNET_new (struct StopHelperState);
+ shs->helper_start_label = helper_start_label;
+ shs->local_m = topology->nodes_m;
+ shs->global_n = topology->namespaces_n;
+
+ struct GNUNET_TESTING_Command cmd = {
+ .cls = shs,
+ .label = label,
+ .run = &stop_testing_system_run,
+ .cleanup = &stop_testing_system_cleanup,
+ .traits = &stop_testing_system_traits
+ };
+
+ return cmd;
+}
diff --git a/src/testing/testing_api_cmd_netjail_stop_v2.c b/src/testing/testing_api_cmd_netjail_stop_v2.c
new file mode 100644
index 000000000..1d13407d7
--- /dev/null
+++ b/src/testing/testing_api_cmd_netjail_stop_v2.c
@@ -0,0 +1,225 @@
+/*
+ This file is part of GNUnet
+ Copyright (C) 2021 GNUnet e.V.
+
+ GNUnet is free software: you can redistribute it and/or modify it
+ under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License,
+ or (at your option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ SPDX-License-Identifier: AGPL3.0-or-later
+ */
+
+/**
+ * @file testing/testing_api_cmd_hello_world.c
+ * @brief Command to stop the netjail script.
+ * @author t3sserakt
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_testing_ng_lib.h"
+
+
+#define NETJAIL_STOP_SCRIPT "./../testing/netjail_stop_v2.sh"
+
+// Child Wait handle
+struct GNUNET_ChildWaitHandle *cwh;
+
+/**
+ * Struct to hold information for callbacks.
+ *
+ */
+struct NetJailState
+{
+ /**
+ * Configuration file for the test topology.
+ */
+ char *topology_config;
+
+ /**
+ * The process id of the start script.
+ */
+ struct GNUNET_OS_Process *stop_proc;
+
+ // Flag indication if the script finished.
+ unsigned int finished;
+};
+
+
+/**
+ * The cleanup function of this cmd frees resources the cmd allocated.
+ *
+ */
+static void
+netjail_stop_cleanup (void *cls,
+ const struct GNUNET_TESTING_Command *cmd)
+{
+ struct NetJailState *ns = cls;
+
+ if (NULL != cwh)
+ {
+ GNUNET_wait_child_cancel (cwh);
+ cwh = NULL;
+ }
+ if (NULL != ns->stop_proc)
+ {
+ GNUNET_assert (0 ==
+ GNUNET_OS_process_kill (ns->stop_proc,
+ SIGKILL));
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_OS_process_wait (ns->stop_proc));
+ GNUNET_OS_process_destroy (ns->stop_proc);
+ ns->stop_proc = NULL;
+ }
+}
+
+
+/**
+ * Trait function of this cmd does nothing.
+ *
+ */
+static int
+netjail_stop_traits (void *cls,
+ const void **ret,
+ const char *trait,
+ unsigned int index)
+{
+ return GNUNET_OK;
+}
+
+
+/**
+ * Callback which will be called if the setup script finished.
+ *
+ */
+static void
+child_completed_callback (void *cls,
+ enum GNUNET_OS_ProcessStatusType type,
+ long unsigned int exit_code)
+{
+ struct NetJailState *ns = cls;
+
+ cwh = NULL;
+ if (0 == exit_code)
+ {
+ ns->finished = GNUNET_YES;
+ }
+ else
+ {
+ ns->finished = GNUNET_SYSERR;
+ }
+ GNUNET_OS_process_destroy (ns->stop_proc);
+ ns->stop_proc = NULL;
+}
+
+
+/**
+* The run method starts the script which deletes the network namespaces.
+*
+* @param cls closure.
+* @param cmd CMD being run.
+* @param is interpreter state.
+*/
+static void
+netjail_stop_run (void *cls,
+ const struct GNUNET_TESTING_Command *cmd,
+ struct GNUNET_TESTING_Interpreter *is)
+{
+ struct NetJailState *ns = cls;
+ char *pid;
+ GNUNET_asprintf (&pid,
+ "%u",
+ getpid ());
+ char *const script_argv[] = {NETJAIL_STOP_SCRIPT,
+ ns->topology_config,
+ pid,
+ NULL};
+ unsigned int helper_check = GNUNET_OS_check_helper_binary (
+ NETJAIL_STOP_SCRIPT,
+ GNUNET_YES,
+ NULL);
+
+ if (GNUNET_NO == helper_check)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "No SUID for %s!\n",
+ NETJAIL_STOP_SCRIPT);
+ GNUNET_TESTING_interpreter_fail ();
+ }
+ else if (GNUNET_NO == helper_check)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "%s not found!\n",
+ NETJAIL_STOP_SCRIPT);
+ GNUNET_TESTING_interpreter_fail ();
+ }
+
+ ns->stop_proc = GNUNET_OS_start_process_vap (GNUNET_OS_INHERIT_STD_ERR,
+ NULL,
+ NULL,
+ NULL,
+ NETJAIL_STOP_SCRIPT,
+ script_argv);
+
+ cwh = GNUNET_wait_child (ns->stop_proc,
+ &child_completed_callback,
+ ns);
+ GNUNET_break (NULL != cwh);
+
+}
+
+
+/**
+ * This function checks the flag NetJailState#finished, if this cmd finished.
+ *
+ */
+static int
+netjail_stop_finish (void *cls,
+ GNUNET_SCHEDULER_TaskCallback cont,
+ void *cont_cls)
+{
+ struct NetJailState *ns = cls;
+
+ if (ns->finished)
+ {
+ cont (cont_cls);
+ }
+ return ns->finished;
+}
+
+
+/**
+ * Create command.
+ *
+ * @param label name for command.
+ * @param topology_config Configuration file for the test topology.
+ * @return command.
+ */
+struct GNUNET_TESTING_Command
+GNUNET_TESTING_cmd_netjail_stop_v2 (const char *label,
+ char *topology_config)
+{
+ struct NetJailState *ns;
+
+ ns = GNUNET_new (struct NetJailState);
+ ns->topology_config = topology_config;
+
+ struct GNUNET_TESTING_Command cmd = {
+ .cls = ns,
+ .label = label,
+ .run = &netjail_stop_run,
+ .finish = &netjail_stop_finish,
+ .cleanup = &netjail_stop_cleanup,
+ .traits = &netjail_stop_traits
+ };
+
+ return cmd;
+}
diff --git a/src/testing/topo.sh b/src/testing/topo.sh
new file mode 100755
index 000000000..090c3053f
--- /dev/null
+++ b/src/testing/topo.sh
@@ -0,0 +1,95 @@
+#!/bin/bash
+
+declare -A K_PLUGIN
+declare -A R_TCP
+declare -A R_UDP
+declare -A P_PLUGIN
+
+extract_attributes()
+{
+ line_key=$1
+ line=$2
+
+ if [ "$line_key" = "P" ]
+ then
+ n=$(echo $line|cut -d \| -f 1|awk -F: '{print $2}')
+ echo $n
+ m=$(echo $line|cut -d \| -f 1|awk -F: '{print $3}')
+ echo $m
+ else
+ number=$(echo $line|cut -d \| -f 1| cut -c 2-|cut -d : -f 2 )
+ echo $number
+ fi
+
+
+ nf=$(echo $line|awk -F: '{print NF}')
+ for ((i=2;i<=$nf;i++))
+ do
+ entry=$(echo $line |awk -v i=$i -F\| '{print $i}')
+ key=$(echo $entry|cut -d { -f 2|cut -d } -f 1|cut -d : -f 1)
+ value=$(echo $entry|cut -d { -f 2|cut -d } -f 1|cut -d : -f 2)
+ if [ "$key" = "tcp_port" ]
+ then
+ echo tcp port: $value
+ R_TCP[$number]=$value
+ elif [ "$key" = "udp_port" ]
+ then
+ echo udp port: $value
+ R_UDP[$number]=$value
+ elif [ "$key" = "plugin" ]
+ then
+ echo plugin: $value
+ echo $line_key
+ if [ "$line_key" = "P" ]
+ then
+ P_PLUGIN[$n,$m]=$value
+ echo $n $m ${P_PLUGIN[$n,$m]}
+ elif [ "$line_key" = "K" ]
+ then
+ K_PLUGIN[$number]=$value
+ fi
+ fi
+ done
+}
+
+read_topology(){
+
+local filename=$1
+while read line; do
+# reading each line
+ echo $line
+ key=$(cut -c -1 <<< $line)
+ if [ "$key" = "M" ]
+ then
+ LOCAL_M=$(cut -d : -f 2 <<< $line)
+ echo $LOCAL_M
+ elif [ "$key" = "N" ]
+ then
+ GLOBAL_N=$(cut -d : -f 2 <<< $line)
+ echo $GLOBAL_N
+ elif [ "$key" = "X" ]
+ then
+ KNOWN=$(cut -d : -f 2 <<< $line)
+ echo $KNOWN
+ elif [ "$key" = "T" ]
+ then
+ PLUGIN=$(cut -d : -f 2 <<< $line)
+ echo $PLUGIN
+ elif [ "$key" = "K" ]
+ then
+ echo know node
+ extract_attributes $key $line
+ elif [ "$key" = "R" ]
+ then
+ echo router
+ extract_attributes $key $line
+ elif [ "$key" = "P" ]
+ then
+ echo node
+ extract_attributes $key $line
+ fi
+done < $filename
+}
+
+
+