aboutsummaryrefslogtreecommitdiff
path: root/src/testing/testing_api_cmd_netjail_start_testsystem.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/testing/testing_api_cmd_netjail_start_testsystem.c')
-rw-r--r--src/testing/testing_api_cmd_netjail_start_testsystem.c811
1 files changed, 0 insertions, 811 deletions
diff --git a/src/testing/testing_api_cmd_netjail_start_testsystem.c b/src/testing/testing_api_cmd_netjail_start_testsystem.c
deleted file mode 100644
index 0624a7f46..000000000
--- a/src/testing/testing_api_cmd_netjail_start_testsystem.c
+++ /dev/null
@@ -1,811 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file testing/testing_api_cmd_hello_world.c
23 * @brief Command to start the netjail peers.
24 * @author t3sserakt
25 */
26#include "platform.h"
27#include "gnunet_testing_ng_lib.h"
28#include "gnunet_testing_netjail_lib.h"
29#include "testing_cmds.h"
30
31#define NETJAIL_EXEC_SCRIPT "netjail_exec.sh"
32
33#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
34
35/**
36 * Generic logging shortcut
37 */
38#define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__)
39
40/**
41 * Struct to store messages send/received by the helper into a DLL
42 *
43 */
44struct HelperMessage
45{
46
47 /**
48 * Kept in a DLL.
49 */
50 struct HelperMessage *next;
51
52 /**
53 * Kept in a DLL.
54 */
55 struct HelperMessage *prev;
56
57 /**
58 * Size of the original message.
59 */
60 uint16_t bytes_msg;
61
62 /* Followed by @e bytes_msg of msg.*/
63};
64
65
66/**
67 * Struct to store information handed over to callbacks.
68 *
69 */
70struct NetJailState
71{
72 /**
73 * Global state of the interpreter, used by a command
74 * to access information about other commands.
75 */
76 struct GNUNET_TESTING_Interpreter *is;
77
78 /**
79 * Context for our asynchronous completion.
80 */
81 struct GNUNET_TESTING_AsyncContext ac;
82
83 /**
84 * The complete topology information.
85 */
86 struct GNUNET_TESTING_NetjailTopology *topology;
87
88 /**
89 * Array with handles of helper processes.
90 */
91 const struct GNUNET_HELPER_Handle **helper;
92
93 /**
94 * Size of the array NetJailState#helper.
95 *
96 */
97 unsigned int n_helper;
98
99 /**
100 * Number of nodes in a natted subnet.
101 *
102 */
103 unsigned int local_m;
104
105 /**
106 * Number of natted subnets.
107 *
108 */
109 unsigned int global_n;
110
111 /**
112 * Number of global known nodes.
113 *
114 */
115 unsigned int known;
116
117
118 /**
119 * Number of test environments started.
120 *
121 */
122 unsigned int number_of_testsystems_started;
123
124 /**
125 * Number of peers started.
126 *
127 */
128 unsigned int number_of_peers_started;
129
130 /**
131 * Number of local tests finished.
132 *
133 */
134 unsigned int number_of_local_tests_finished;
135
136 /**
137 * Number of local tests prepared to finish.
138 *
139 */
140 unsigned int number_of_local_tests_prepared;
141
142 /**
143 * Name of the test case plugin the helper will load.
144 *
145 */
146 char *plugin_name;
147
148 /**
149 * Shall we read the topology from file, or from a string.
150 */
151 unsigned int *read_file;
152
153 /**
154 * String with topology data or name of topology file.
155 */
156 char *topology_data;
157
158 /**
159 * Time after this cmd has to finish.
160 */
161 struct GNUNET_TIME_Relative timeout;
162
163 /**
164 * Timeout task.
165 */
166 struct GNUNET_SCHEDULER_Task *timeout_task;
167};
168
169/**
170 * Struct containing the number of the test environment and the NetJailState which
171 * will be handed to callbacks specific to a test environment.
172 */
173struct TestingSystemCount
174{
175 /**
176 * Kept in a DLL.
177 */
178 struct TestingSystemCount *next;
179
180 /**
181 * Kept in a DLL.
182 */
183 struct TestingSystemCount *prev;
184
185 /**
186 * The send handle for the helper
187 */
188 struct GNUNET_HELPER_SendHandle *shandle;
189
190 /**
191 * The number of the test environment.
192 *
193 */
194 unsigned int count;
195
196 /**
197 * Struct to store information handed over to callbacks.
198 *
199 */
200 struct NetJailState *ns;
201
202 /**
203 * The messages send to the helper.
204 */
205 struct GNUNET_MessageHeader *msg;
206};
207
208/**
209* Code to clean up resource this cmd used.
210*
211* @param cls closure
212*/
213static void
214netjail_exec_cleanup (void *cls)
215{
216 struct NetJailState *ns = cls;
217
218 GNUNET_free (ns);
219}
220
221
222/**
223 * This function prepares an array with traits.
224 *
225 */
226static enum GNUNET_GenericReturnValue
227netjail_exec_traits (void *cls,
228 const void **ret,
229 const char *trait,
230 unsigned int index)
231{
232 struct NetJailState *ns = cls;
233 const struct GNUNET_HELPER_Handle **helper = ns->helper;
234
235
236 struct GNUNET_TESTING_Trait traits[] = {
237 GNUNET_TESTING_make_trait_helper_handles (helper),
238 GNUNET_TESTING_trait_end ()
239 };
240
241 return GNUNET_TESTING_get_trait (traits,
242 ret,
243 trait,
244 index);
245}
246
247
248/**
249 * Continuation function from GNUNET_HELPER_send()
250 *
251 * @param cls closure
252 * @param result GNUNET_OK on success,
253 * GNUNET_NO if helper process died
254 * GNUNET_SYSERR during GNUNET_HELPER_stop
255 */
256static void
257clear_msg (void *cls, int result)
258{
259 struct TestingSystemCount *tbc = cls;
260
261 GNUNET_assert (NULL != tbc->shandle);
262 /*GNUNET_free (tbc->shandle);
263 tbc->shandle = NULL;*/
264 GNUNET_free (tbc->msg);
265 tbc->msg = NULL;
266}
267
268
269static void
270send_message_to_locals (
271 unsigned int i,
272 unsigned int j,
273 struct NetJailState *ns,
274 struct GNUNET_MessageHeader *header
275 )
276{
277 const struct GNUNET_HELPER_Handle *helper;
278 struct TestingSystemCount *tbc;
279
280 LOG (GNUNET_ERROR_TYPE_DEBUG,
281 "send message of type %u to locals\n",
282 header->type);
283 tbc = GNUNET_new (struct TestingSystemCount);
284 tbc->ns = ns;
285 // 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.
286 if (0 == i)
287 tbc->count = j; // + total_number;
288 else
289 tbc->count = (i - 1) * ns->local_m + j + ns->known; // + total_number ;
290
291 helper = ns->helper[tbc->count - 1];// - total_number];
292
293
294
295 struct GNUNET_HELPER_SendHandle *sh = GNUNET_HELPER_send (
296 (struct GNUNET_HELPER_Handle *) helper,
297 header,
298 GNUNET_NO,
299 &clear_msg,
300 tbc);
301
302 tbc->shandle = sh;
303 // GNUNET_array_append (tbc->shandle, tbc->n_shandle, sh);
304}
305
306
307static void
308send_all_local_tests_prepared (unsigned int i, unsigned int j, struct
309 NetJailState *ns)
310{
311 struct GNUNET_CMDS_ALL_LOCAL_TESTS_PREPARED *reply;
312 size_t msg_length;
313
314
315 msg_length = sizeof(struct GNUNET_CMDS_ALL_LOCAL_TESTS_PREPARED);
316 reply = GNUNET_new (struct GNUNET_CMDS_ALL_LOCAL_TESTS_PREPARED);
317 reply->header.type = htons (
318 GNUNET_MESSAGE_TYPE_CMDS_HELPER_ALL_LOCAL_TESTS_PREPARED);
319 reply->header.size = htons ((uint16_t) msg_length);
320
321 send_message_to_locals (i, j, ns, &reply->header);
322}
323
324
325static void
326send_all_peers_started (unsigned int i, unsigned int j, struct NetJailState *ns)
327{
328
329 struct GNUNET_CMDS_ALL_PEERS_STARTED *reply;
330 size_t msg_length;
331
332
333 msg_length = sizeof(struct GNUNET_CMDS_ALL_PEERS_STARTED);
334 reply = GNUNET_new (struct GNUNET_CMDS_ALL_PEERS_STARTED);
335 reply->header.type = htons (
336 GNUNET_MESSAGE_TYPE_CMDS_HELPER_ALL_PEERS_STARTED);
337 reply->header.size = htons ((uint16_t) msg_length);
338
339 send_message_to_locals (i, j, ns, &reply->header);
340}
341
342
343/**
344 * Functions with this signature are called whenever a
345 * complete message is received by the tokenizer.
346 *
347 * Do not call GNUNET_SERVER_mst_destroy in callback
348 *
349 * @param cls closure
350 * @param client identification of the client
351 * @param message the actual message
352 *
353 * @return #GNUNET_OK on success, #GNUNET_SYSERR to stop further processing
354 */
355static int
356helper_mst (void *cls, const struct GNUNET_MessageHeader *message)
357{
358 // struct TestingSystemCount *tbc = cls;
359 struct NetJailState *ns = cls;
360 unsigned int total_number = ns->local_m * ns->global_n + ns->known;
361 uint16_t message_type = ntohs (message->type);
362
363 switch (message_type)
364 {
365 case GNUNET_MESSAGE_TYPE_CMDS_HELPER_REPLY:
366 ns->number_of_testsystems_started++;
367 break;
368 case GNUNET_MESSAGE_TYPE_CMDS_HELPER_PEER_STARTED:
369 ns->number_of_peers_started++;
370 if (ns->number_of_peers_started == total_number)
371 {
372 for (int i = 1; i <= ns->known; i++)
373 {
374 send_all_peers_started (0,i, ns);
375 }
376 for (int i = 1; i <= ns->global_n; i++)
377 {
378 for (int j = 1; j <= ns->local_m; j++)
379 {
380 send_all_peers_started (i,j, ns);
381 }
382 }
383 ns->number_of_peers_started = 0;
384 }
385 break;
386 case GNUNET_MESSAGE_TYPE_CMDS_HELPER_LOCAL_TEST_PREPARED:
387 ns->number_of_local_tests_prepared++;
388 if (ns->number_of_local_tests_prepared == total_number)
389 {
390 for (int i = 1; i <= ns->known; i++)
391 {
392 send_all_local_tests_prepared (0,i, ns);
393 }
394
395 for (int i = 1; i <= ns->global_n; i++)
396 {
397 for (int j = 1; j <= ns->local_m; j++)
398 {
399 send_all_local_tests_prepared (i,j, ns);
400 }
401 }
402 }
403 break;
404 case GNUNET_MESSAGE_TYPE_CMDS_HELPER_LOCAL_FINISHED:
405 ns->number_of_local_tests_finished++;
406 if (ns->number_of_local_tests_finished == total_number)
407 {
408 GNUNET_SCHEDULER_cancel (ns->timeout_task);
409 GNUNET_TESTING_async_finish (&ns->ac);
410 }
411 break;
412 default:
413 // We received a message we can not handle.
414 GNUNET_assert (0);
415 }
416 /*if (GNUNET_MESSAGE_TYPE_CMDS_HELPER_REPLY == ntohs (message->type))
417 {
418 ns->number_of_testsystems_started++;
419 }
420 else if (GNUNET_MESSAGE_TYPE_CMDS_HELPER_PEER_STARTED == ntohs (
421 message->type))
422 {
423 ns->number_of_peers_started++;
424 if (ns->number_of_peers_started == total_number)
425 {
426 for (int i = 1; i <= ns->known; i++)
427 {
428 send_all_peers_started (0,i, ns);
429 }
430
431 for (int i = 1; i <= ns->global_n; i++)
432 {
433 for (int j = 1; j <= ns->local_m; j++)
434 {
435 send_all_peers_started (i,j, ns);
436 }
437 }
438 ns->number_of_peers_started = 0;
439 }
440 }
441 else if (GNUNET_MESSAGE_TYPE_CMDS_HELPER_LOCAL_TEST_PREPARED == ntohs (
442 message->type))
443 {
444 ns->number_of_local_tests_prepared++;
445 if (ns->number_of_local_tests_prepared == total_number)
446 {
447 for (int i = 1; i <= ns->known; i++)
448 {
449 send_all_local_tests_prepared (0,i, ns);
450 }
451
452 for (int i = 1; i <= ns->global_n; i++)
453 {
454 for (int j = 1; j <= ns->local_m; j++)
455 {
456 send_all_local_tests_prepared (i,j, ns);
457 }
458 }
459 }
460 }
461 else if (GNUNET_MESSAGE_TYPE_CMDS_HELPER_LOCAL_FINISHED == ntohs (
462 message->type))
463 {
464 ns->number_of_local_tests_finished++;
465 if (ns->number_of_local_tests_finished == total_number)
466 {
467 GNUNET_TESTING_async_finish (&ns->ac);
468 }
469 }
470 else
471 {
472 // We received a message we can not handle.
473 GNUNET_assert (0);
474 }*/
475
476
477 LOG (GNUNET_ERROR_TYPE_DEBUG,
478 "total %u sysstarted %u peersstarted %u prep %u finished %u %u %u %u\n",
479 total_number,
480 ns->number_of_testsystems_started,
481 ns->number_of_peers_started,
482 ns->number_of_local_tests_prepared,
483 ns->number_of_local_tests_finished,
484 ns->local_m,
485 ns->global_n,
486 ns->known);
487
488
489
490
491 return GNUNET_OK;
492}
493
494
495/**
496 * Callback called if there was an exception during execution of the helper.
497 *
498 */
499static void
500exp_cb (void *cls)
501{
502 struct NetJailState *ns = cls;
503
504 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Called exp_cb.\n");
505 GNUNET_SCHEDULER_cancel (ns->timeout_task);
506 GNUNET_TESTING_async_fail (&(ns->ac));
507}
508
509
510/**
511 * Function to initialize a init message for the helper.
512 *
513 * @param plugin_name Name of the test case plugin the helper will load.
514 *
515 */
516static struct GNUNET_CMDS_HelperInit *
517create_helper_init_msg_ (const char *plugin_name)
518{
519 struct GNUNET_CMDS_HelperInit *msg;
520 uint16_t plugin_name_len;
521 uint16_t msg_size;
522
523 GNUNET_assert (NULL != plugin_name);
524 plugin_name_len = strlen (plugin_name);
525 msg_size = sizeof(struct GNUNET_CMDS_HelperInit) + plugin_name_len;
526 msg = GNUNET_malloc (msg_size);
527 msg->header.size = htons (msg_size);
528 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CMDS_HELPER_INIT);
529 msg->plugin_name_size = htons (plugin_name_len);
530 GNUNET_memcpy ((char *) &msg[1],
531 plugin_name,
532 plugin_name_len);
533 return msg;
534}
535
536
537/**
538 * Function which start a single helper process.
539 *
540 */
541static void
542start_helper (struct NetJailState *ns,
543 unsigned int m,
544 unsigned int n)
545{
546 struct GNUNET_HELPER_Handle *helper;
547 struct GNUNET_CMDS_HelperInit *msg;
548 struct TestingSystemCount *tbc;
549 char *m_char;
550 char *n_char;
551 char *global_n_char;
552 char *local_m_char;
553 char *known_char;
554 char *node_id;
555 char *plugin;
556 char *read_file;
557 pid_t pid;
558 unsigned int script_num;
559 struct GNUNET_ShortHashCode *hkey;
560 struct GNUNET_HashCode hc;
561 struct GNUNET_TESTING_NetjailTopology *topology = ns->topology;
562 struct GNUNET_TESTING_NetjailNode *node;
563 struct GNUNET_TESTING_NetjailNamespace *namespace;
564 char *data_dir;
565 char *script_name;
566
567
568 if (0 == n)
569 script_num = m - 1;
570 else
571 script_num = n - 1 + (n - 1) * ns->local_m + m + ns->known;
572 pid = getpid ();
573
574 GNUNET_asprintf (&m_char, "%u", m);
575 GNUNET_asprintf (&n_char, "%u", n);
576 GNUNET_asprintf (&local_m_char, "%u", ns->local_m);
577 GNUNET_asprintf (&global_n_char, "%u",ns->global_n);
578 GNUNET_asprintf (&known_char, "%u",ns->known);
579 GNUNET_asprintf (&node_id, "%06x-%08x\n",
580 pid,
581 script_num);
582 // GNUNET_asprintf (&topology_data, "'%s'", ns->topology_data);
583 GNUNET_asprintf (&read_file, "%u", *(ns->read_file));
584
585 data_dir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR);
586 GNUNET_asprintf (&script_name, "%s%s", data_dir, NETJAIL_EXEC_SCRIPT);
587 unsigned int helper_check = GNUNET_OS_check_helper_binary (
588 script_name,
589 GNUNET_YES,
590 NULL);
591
592 tbc = GNUNET_new (struct TestingSystemCount);
593 tbc->ns = ns;
594
595 if (GNUNET_NO == helper_check)
596 {
597 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
598 "No SUID for %s!\n",
599 script_name);
600 GNUNET_TESTING_interpreter_fail (ns->is);
601 }
602 else if (GNUNET_NO == helper_check)
603 {
604 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
605 "%s not found!\n",
606 script_name);
607 GNUNET_TESTING_interpreter_fail (ns->is);
608 }
609
610 LOG (GNUNET_ERROR_TYPE_DEBUG,
611 "sysstarted %u peersstarted %u prep %u finished %u %u %u %u\n",
612 ns->number_of_testsystems_started,
613 ns->number_of_peers_started,
614 ns->number_of_local_tests_prepared,
615 ns->number_of_local_tests_finished,
616 ns->local_m,
617 ns->global_n,
618 ns->known);
619 {
620 char *const script_argv[] = {script_name,
621 m_char,
622 n_char,
623 GNUNET_OS_get_libexec_binary_path (
624 HELPER_CMDS_BINARY),
625 global_n_char,
626 local_m_char,
627 node_id,
628 read_file,
629 ns->topology_data,
630 NULL};
631 helper = GNUNET_HELPER_start (
632 GNUNET_YES,
633 script_name,
634 script_argv,
635 &helper_mst,
636 &exp_cb,
637 ns);
638 GNUNET_array_append (ns->helper, ns->n_helper, helper);
639 }
640
641 tbc->count = ns->n_helper;
642 hkey = GNUNET_new (struct GNUNET_ShortHashCode);
643
644 plugin = topology->plugin;
645
646 if (0 == m)
647 {
648
649 GNUNET_CRYPTO_hash (&n, sizeof(n), &hc);
650 memcpy (hkey,
651 &hc,
652 sizeof (*hkey));
653 if (1 == GNUNET_CONTAINER_multishortmap_contains (topology->map_globals,
654 hkey))
655 {
656 node = GNUNET_CONTAINER_multishortmap_get (topology->map_globals,
657 hkey);
658 if (NULL != node->plugin)
659 plugin = node->plugin;
660 }
661
662 }
663 else
664 {
665 GNUNET_CRYPTO_hash (&m, sizeof(m), &hc);
666 memcpy (hkey,
667 &hc,
668 sizeof (*hkey));
669 if (1 == GNUNET_CONTAINER_multishortmap_contains (topology->map_namespaces,
670 hkey))
671 {
672 namespace = GNUNET_CONTAINER_multishortmap_get (topology->map_namespaces,
673 hkey);
674 GNUNET_CRYPTO_hash (&n, sizeof(n), &hc);
675 memcpy (hkey,
676 &hc,
677 sizeof (*hkey));
678 if (1 == GNUNET_CONTAINER_multishortmap_contains (namespace->nodes,
679 hkey))
680 {
681 node = GNUNET_CONTAINER_multishortmap_get (namespace->nodes,
682 hkey);
683 if (NULL != node->plugin)
684 plugin = node->plugin;
685 }
686 }
687
688
689 }
690
691 msg = create_helper_init_msg_ (plugin);
692
693 // GNUNET_array_append (tbc->shandle, tbc->n_shandle,
694 tbc->shandle = GNUNET_HELPER_send (
695 helper,
696 &msg->header,
697 GNUNET_NO,
698 &clear_msg,
699 tbc); // );
700
701 if (NULL == tbc->shandle)// [tbc->count - 1])
702 {
703 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
704 "Send handle is NULL!\n");
705 GNUNET_free (msg);
706 GNUNET_TESTING_interpreter_fail (ns->is);
707 }
708 GNUNET_free (hkey);
709}
710
711
712/**
713 * Function run when the cmd terminates (good or bad) with timeout.
714 *
715 * @param cls the interpreter state
716 */
717static void
718do_timeout (void *cls)
719{
720 struct NetJailState *ns = cls;
721 struct GNUNET_TESTING_Command *cmd;
722
723 ns->timeout_task = NULL;
724 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
725 "Terminating cmd due to global timeout\n");
726 cmd = GNUNET_TESTING_interpreter_get_current_command (ns->is);
727 GNUNET_TESTING_async_finish (cmd->ac);
728}
729
730
731/**
732* This function starts a helper process for each node.
733*
734* @param cls closure.
735* @param cmd CMD being run.
736* @param is interpreter state.
737*/
738static void
739netjail_exec_run (void *cls,
740 struct GNUNET_TESTING_Interpreter *is)
741{
742 struct NetJailState *ns = cls;
743
744 ns->is = is;
745 for (int i = 1; i <= ns->known; i++)
746 {
747 start_helper (ns,
748 i,
749 0);
750 }
751
752 for (int i = 1; i <= ns->global_n; i++)
753 {
754 for (int j = 1; j <= ns->local_m; j++)
755 {
756 start_helper (ns,
757 j,
758 i);
759 }
760 }
761 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
762 "Adding timeout %s\n",
763 GNUNET_STRINGS_relative_time_to_string (ns->timeout, GNUNET_NO));
764 ns->timeout_task
765 = GNUNET_SCHEDULER_add_delayed (ns->timeout,
766 &do_timeout,
767 ns);
768}
769
770
771/**
772 * Create command.
773 *
774 * @param label Name for the command.
775 * @param topology The complete topology information.
776 * @param read_file Flag indicating if the the name of the topology file is send to the helper, or a string with the topology data.
777 * @param topology_data If read_file is GNUNET_NO, topology_data holds the string with the topology.
778 * @param timeout Before this timeout is reached this cmd MUST finish.
779 * @return command.
780 */
781struct GNUNET_TESTING_Command
782GNUNET_TESTING_cmd_netjail_start_testing_system (
783 const char *label,
784 struct GNUNET_TESTING_NetjailTopology *topology,
785 unsigned int *read_file,
786 char *topology_data,
787 struct GNUNET_TIME_Relative timeout)
788{
789 struct NetJailState *ns;
790
791 ns = GNUNET_new (struct NetJailState);
792 ns->local_m = topology->nodes_m;
793 ns->global_n = topology->namespaces_n;
794 ns->known = topology->nodes_x;
795 ns->plugin_name = topology->plugin;
796 ns->topology = topology;
797 ns->read_file = read_file;
798 ns->topology_data = topology_data;
799 ns->timeout = GNUNET_TIME_relative_subtract (timeout, TIMEOUT);
800
801 struct GNUNET_TESTING_Command cmd = {
802 .cls = ns,
803 .label = label,
804 .run = &netjail_exec_run,
805 .ac = &ns->ac,
806 .cleanup = &netjail_exec_cleanup,
807 .traits = &netjail_exec_traits
808 };
809
810 return cmd;
811}