My Project
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros
cli.c
Go to the documentation of this file.
1 /*
2 START OF LICENSE STUB
3  DeDOS: Declarative Dispersion-Oriented Software
4  Copyright (C) 2017 University of Pennsylvania, Georgetown University
5 
6  This program is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program. If not, see <http://www.gnu.org/licenses/>.
18 END OF LICENSE STUB
19 */
20 #include <stdio.h>
21 #include <string.h>
22 #include <stdlib.h>
23 #include <pthread.h>
24 #include <sys/types.h>
25 #include <unistd.h>
26 #include <arpa/inet.h>
27 #include <strings.h>
28 
29 #include "controller_stats.h"
30 #include "scheduling.h"
31 #include "logging.h"
32 #include "communication.h"
33 #include "cli.h"
34 #include "dedos_msu_msg_type.h"
35 #include "runtime_messages.h"
36 #include "controller_dfg.h"
37 #include "runtime_communication.h"
38 #include "dfg.h"
39 #include "api.h"
40 
41 #define NEXT_MSU_LOCAL 1
42 #define NEXT_MSU_REMOTE 2
43 
44 #define BLD "\e[1m"
45 #define UL "\e[4m"
46 #define NOSTYLE "\e[0m"
47 
48 #define HELP_PREAMBLE \
49  "\nList of available commands : \n" \
50  "\n" \
51  "\t******* Note: " UL "ARGUMENTS" NOSTYLE " fields are required, excluding " \
52  UL "[BRACKETED]" NOSTYLE " ****\n" \
53  "\n"
54 
55 
56 struct cmd_action {
57  char cmd[32];
58  int (*action)(char*);
59  char args[32][16];
60  char help[256];
61 };
62 
63 
64 static int parse_show_runtimes(char *args) {
65  struct dedos_dfg *dfg = get_dfg();
66  for (int i=0; i<dfg->n_runtimes; i++) {
67  int fd = runtime_fd(dfg->runtimes[i]->id);
68  printf("Runtime id: %d -- ", dfg->runtimes[i]->id);
69  if (fd <= 0) {
70  printf("NOT CONNECTED\n");
71  } else {
72  printf("fd: %d\n", fd);
73  }
74  }
75  return 0;
76 }
77 
78 #define NEXT_ARG(arg, args) \
79  if ( ( arg = strtok(args, " \r\n") ) == NULL){ \
80  log_error("Missing required argument"); \
81  return -1; \
82  }
83 
90 static int parse_allocate() {
91  // Pick only msus where no scheduling item is initialized
92  //struct dfg_config *dfg;
93  //dfg = get_dfg();
94 
95  struct to_schedule *ts = NULL;
96  ts = malloc(sizeof(struct to_schedule));
97  if (ts == NULL) {
98  debug("Could not allocate memory for to_schedule");
99  return -1;
100  }
101 
102  int to_allocate_msus[MAX_MSU];
103  int num_to_alloc = 0;
104 
105  //int n;
106  /*
107  for (n = 0; n < dfg->vertex_cnt; ++n) {
108  if (dfg->vertices[n]->scheduling == NULL) {
109  to_allocate_msus[n] = dfg->vertices[n]->msu_id;
110  num_to_alloc++;
111  }
112  }
113  */
114 
115  ts->msu_ids = to_allocate_msus;
116  ts->num_msu = num_to_alloc;
117 
118  //TODO: allocate(ts);
119  return 0;
120 }
121 
127 static int parse_show_stats(char *args) {
128  char *arg;
129  NEXT_ARG(arg, args);
130  int msu_id = atoi(arg);
131 
132  struct dfg_msu *msu = get_dfg_msu(msu_id);
133  if (msu == NULL) {
134  printf("MSU id %d is not registered with the controller\n", msu_id);
135  return -1;
136  }
137 
138  show_stats(msu);
139  return 0;
140 }
141 
142 static int parse_show_msus(char *args) {
143  char *arg;
144  NEXT_ARG(arg, args);
145  int runtime_id = atoi(arg);
146  struct dfg_runtime *rt = get_dfg_runtime(runtime_id);
147 
148  if (rt == NULL) {
149  printf("Could not retrieve runtime %d from DFG", runtime_id);
150  return -1;
151  }
152 
153  //TODO: int rtn = send_report_msus_msg(rt);
154 
155  struct dedos_dfg *dfg = get_dfg();
156  for (int i=0; i<dfg->n_msus; i++) {
157  struct dfg_msu *msu = dfg->msus[i];
158  if (msu->scheduling.runtime == rt) {
159  printf("ID: %d\t Thread: %d \t Type: %s (%d)\n",
160  msu->id, msu->scheduling.thread->id, msu->type->name, msu->type->id);
161  }
162  }
163 
164 
165  int rtn = 0;
166 
167  if (rtn < 0) {
168  printf("Could not send report MSUs message to runtime %d", runtime_id);
169  return -1;
170  }
171 
172  return 0;
173 }
174 
175 static int parse_add_msu(char *args) {
176  char *arg;
177  NEXT_ARG(arg, args);
178  int runtime_id = atoi(arg);
179 
180  NEXT_ARG(arg, NULL);
181  int msu_type = atoi(arg);
182 
183  NEXT_ARG(arg, NULL);
184  int msu_id = atoi(arg);
185 
186  char *msu_mode;
187  NEXT_ARG(msu_mode, NULL);
188 
189  int thread_id;
190  NEXT_ARG(arg, NULL);
191  thread_id = atoi(arg);
192 
193  char *vertex_type = strtok(NULL, "\r\n|");
194  if (vertex_type == NULL) {
195  vertex_type = "";
196  }
197 
198  char *init_data;
199  char data[MAX_INIT_DATA_LEN];
200  bzero(data, MAX_INIT_DATA_LEN);
201 
202  init_data = strtok(NULL, "\r\n");
203  if (init_data != NULL) {
204  debug("init data: %s, len: %zu", init_data, strlen(init_data));
205  memcpy(data, init_data, strlen(init_data));
206  }
207 
208  int ret = add_msu(msu_id, msu_type, data, msu_mode, vertex_type, thread_id, runtime_id);
209  if (ret == -1) {
210  log_error("Could not trigger new MSU creation");
211  }
212 
213  return ret;
214 }
215 
216 static int parse_del_msu(char *args) {
217  char *arg;
218  NEXT_ARG(arg, NULL);
219  int msu_id = atoi(arg);
220 
221  int rtn = remove_msu(msu_id);
222 
223  if ( rtn < 0 ){
224  log_error("Could not deletion of MSU %d", msu_id);
225  }
226  return rtn;
227 }
228 
229 static int parse_add_route(char *args) {
230  char *arg;
231  NEXT_ARG(arg, NULL);
232  int route_id = atoi(arg);
233 
234  NEXT_ARG(arg, NULL);
235  int msu_id = atoi(arg);
236 
237  int rtn = add_route_to_msu(route_id, msu_id);
238  if ( rtn < 0 ) {
239  log_error("Could not add route %d to msu %d", route_id, msu_id);
240  }
241  return rtn;
242 }
243 
244 static int parse_del_route(char *args) {
245  char *arg;
246  NEXT_ARG(arg, NULL);
247  int route_id = atoi(arg);
248 
249  NEXT_ARG(arg, NULL);
250  int msu_id = atoi(arg);
251 
252  // TODO: int rtn = del_route_from_msu(msu_id, route_id);
253  int rtn = 0;
254  if ( rtn < 0 ) {
255  log_error("Could not delete route %d from msu %d", route_id, msu_id);
256  }
257  return rtn;
258 }
259 
260 static int parse_add_endpoint(char *args) {
261  char *arg;
262  NEXT_ARG(arg, NULL);
263  int route_id = atoi(arg);
264 
265  NEXT_ARG(arg, NULL);
266  int msu_id = atoi(arg);
267 
268  NEXT_ARG(arg, NULL);
269  uint32_t key = (uint32_t)atoi(arg);
270 
271  int rtn = add_endpoint(msu_id, route_id, key);
272  if (rtn < 0) {
273  log_error("Could not add endpoint %d to route %d", msu_id, route_id);
274  }
275  return rtn;
276 }
277 
278 static int parse_del_endpoint(char *args) {
279  char *arg;
280  NEXT_ARG(arg, NULL);
281  int route_id = atoi(arg);
282 
283  NEXT_ARG(arg, NULL);
284  int msu_id = atoi(arg);
285 
286  int rtn = del_endpoint(msu_id, route_id);
287  if (rtn < 0) {
288  log_error("Could not delete endpoint %d from route %d", msu_id, route_id);
289  }
290  return rtn;
291 }
292 
293 static int parse_mod_endpoint(char *args) {
294  char *arg;
295  NEXT_ARG(arg, args);
296  int route_id = atoi(arg);
297 
298  NEXT_ARG(arg, NULL);
299  int msu_id = atoi(arg);
300 
301  NEXT_ARG(arg, NULL);
302  uint32_t key = (uint32_t)atoi(arg);
303 
304  int rtn = mod_endpoint(msu_id, route_id, key);
305  if (rtn < 0) {
306  log_error("Could not modify range for endpoiont %d on route %d to %u",
307  msu_id, route_id, key);
308  }
309  return rtn;
310 }
311 
312 
313 static int parse_create_thread(char *args) {
314  char *arg;
315  NEXT_ARG(arg, args);
316  int runtime_id = atoi(arg);
317 
318  NEXT_ARG(arg, NULL);
319  int thread_id = atoi(arg);
320 
321  char *mode;
322  NEXT_ARG(mode, NULL);
323 
324  int rtn = create_worker_thread(thread_id, runtime_id, mode);
325 
326  if ( rtn < 0 ) {
327  log_error("Could not create new worker thread on runtime %d", runtime_id);
328  }
329 
330  return rtn;
331 }
332 
333 static int parse_load_cfg(char *args) {
334  char *filename;
335  NEXT_ARG(filename, args);
336 
337  FILE *f = fopen(filename, "r");
338 
339  if ( f == NULL ) {
340  log_error("Could not open cfg file %s", filename);
341  return -1;
342  }
343 
344  char *line = NULL;
345  size_t len = 0;
346  int read;
347  while ( ( read = getline(&line, &len, f) ) != -1 ) {
348  parse_cmd_action(line);
349  sleep(1);
350  }
351 
352  fclose(f);
353  free(line);
354 
355  return 0;
356 }
357 
358 static int parse_clone_msu(char *args) {
359  char *msu_c;
360  NEXT_ARG(msu_c, args);
361 
362  int id = atoi(msu_c);
363 
364  struct dfg_msu *to_clone = get_dfg_msu(id);
365  if (to_clone == NULL) {
366  log_error("MSU %d does not exist", id);
367  return -1;
368  }
369  struct dfg_msu *cloned = clone_msu(id);
370  if (cloned == NULL) {
371  log_error("Could not clone msu %d", id);
372  return -1;
373  }
374  return 0;
375 }
376 
377 static int parse_unclone_msu(char *args) {
378  char *msu_c;
379  NEXT_ARG(msu_c, args);
380 
381  int id = atoi(msu_c);
382 
383  struct dfg_msu *msu = get_dfg_msu(id);
384 
385  if (msu == NULL) {
386  log_error("Msu %d does not exist", id);
387  return -1;
388  }
389 
390  int rtn = unclone_msu(id);
391  if (rtn < 0) {
392  log_error("Could not unclone msu %d", id);
393  return -1;
394  }
395  return 0;
396 }
397 
398 static int parse_show_routes(char *args) {
399  char *msu_c;
400  NEXT_ARG(msu_c, args);
401 
402  int id = atoi(msu_c);
403 
404  struct dfg_msu *msu = get_dfg_msu(id);
405 
406  if (msu == NULL) {
407  log_error("Msu %d does not exist", id);
408  return -1;
409  }
410  for (int i=0; i<msu->scheduling.n_routes; i++) {
411  struct dfg_route *route = msu->scheduling.routes[i];
412  printf("Route: %d\tType: %d\n", route->id, route->msu_type->id);
413  }
414  return 0;
415 }
416 
417 static int parse_show_route(char *args) {
418  char *route_id_c;
419  NEXT_ARG(route_id_c, args);
420 
421  int id = atoi(route_id_c);
422 
423  struct dfg_route *route = get_dfg_route(id);
424  if (route == NULL) {
425  log_error("Route %d does not exist", id);
426  return -1;
427  }
428 
429  for (int i=0; i<route->n_endpoints; i++) {
430  struct dfg_route_endpoint *ep = route->endpoints[i];
431  printf("Destination: %d\tKey: %d\n", ep->msu->id, (int)ep->key);
432  }
433  return 0;
434 }
435 
436 
437 static int parse_help(char *cmd);
438 
440  {"show runtimes", parse_show_runtimes, {},
441  "List connected runtimes and socket num"},
442 
443  {"show msus", parse_show_msus, {"RUNTIME-ID"},
444  "Get MSUs running on the runtime" },
445 
446  {"show stats", parse_show_stats, {"MSU-ID"},
447  "display stored time serie for a given msu"},
448 
449  {"show routes", parse_show_routes, {"MSU-ID"},
450  "display routes attached to a given msu"},
451 
452  {"show route", parse_show_route, {"MSU-ID"},
453  "display endpoints of a given route"},
454 
455  {"clone msu", parse_clone_msu, {"MSU-ID"},
456  "clones and schedules the clone of an MSU"},
457 
458  {"unclone msu", parse_unclone_msu, {"MSU-ID"},
459  "Removes an MSU and dependencies"},
460 
461  {"add msu", parse_add_msu,
462  {"RUNTIME-ID", "MSU_TYPE", "MSU-ID", "MSU_MODE", "THREAD-ID", "[VERTEX_TYPE]",
463  "[ | INIT_DATA]"},
464  "(MSU_MODE: blocking/non-blocking; VERTEX_TYPE: entry/exit/entry,exit)"},
465 
466  {"del msu", parse_del_msu, {"MSU-ID"}, "Delete MSU"},
467 
468  {"add route", parse_add_route,
469  {"ROUTE-ID", "MSU-ID"},
470  "Adds an outgoing route to an MSU"},
471 
472  {"del route", parse_del_route,
473  {"ROUTE-ID", "MSU-ID"},
474  "Deletes an outgoing route from an MSU"},
475 
476  {"add endpoint", parse_add_endpoint,
477  {"ROUTE-ID", "MSU-ID", "KEY"},
478  "Adds an MSU as an endpoint to a given route"},
479 
480  {"del endpoint", parse_del_endpoint,
481  {"ROUTE-ID", "MSU-ID"},
482  "Deletes an MSU as an endpoint from a given route"},
483 
484  {"mod endpoint", parse_mod_endpoint,
485  {"ROUTE-ID", "MSU-ID", "KEY"},
486  "Modifies the key range associated with an MSU endpoint on the given route"},
487 
488  {"add thread", parse_create_thread,
489  {"RUNTIME-ID", "THREAD-ID", "MODE"},
490  "(MODE=pinned/unpinned) Creates a worker thread on an unused core"},
491 
492  {"*allocate", parse_allocate, {},
493  "gather all msu not possessing a 'scheduling' object, and compute a placement"},
494 
495  {"loadcfg", parse_load_cfg, {"FILENAME"},
496  "load a suite of commands from a file"},
497 
498  {"help", parse_help, {}, "display available commands"},
499 
500  {"quit", NULL, {}, ""},
501 
502  {"\0", NULL, {}, "\0"}
503 };
504 
505 //TODO: need to check whether an msu or a route are already present in the CFG before proceeding to action
506 int parse_cmd_action(char *cmd) {
507  size_t ln = strlen(cmd) - 1;
508  if (*cmd && cmd[ln] == '\n') {
509  cmd[ln] = '\0';
510  }
511 
512  char cmd_cpy[256];
513  strcpy(cmd_cpy, cmd);
514 
515  int rtn = -1;
516  for ( int i = 0; cmd_actions[i].cmd[0] != '\0'; i++ ){
517  if ( strncasecmp(cmd, cmd_actions[i].cmd, strlen(cmd_actions[i].cmd)) == 0 ) {
518  if ( cmd_actions[i].action ) {
519  rtn = cmd_actions[i].action(cmd + strlen(cmd_actions[i].cmd) + 1 );
520  } else {
521  rtn = 1;
522  }
523  break;
524  }
525  }
526  if (rtn < 0){
527  log_error("Error parsing command: %s", cmd_cpy);
528  }
529 
530  return rtn;
531 }
532 
533 
534 static int parse_help(char *args) {
535  printf(HELP_PREAMBLE);
536  for (int i=0; cmd_actions[i].cmd[0] != '\0'; i++){
537  printf("\t" BLD "%s" NOSTYLE, cmd_actions[i].cmd);
538  for (int j=0; cmd_actions[i].args[j][0]!='\0'; j++) {
539  printf(" " UL "%s" NOSTYLE, cmd_actions[i].args[j]);
540  }
541  printf("\n\t\t%s\n", cmd_actions[i].help);
542  }
543  return 0;
544 }
545 
546 static void* cli_loop() {
547  int next = 0;
548  char *line = NULL;
549  size_t size;
550 
551  parse_help(NULL);
552 
553  do {
554  printf("> Enter command: ");
555  next = getline(&line, &size, stdin);
556  if (next != -1) {
557  if (strcmp(line, "quit\n") == 0) {
558  //TODO CLEAN EXIT
559  exit(0);
560  }
561  parse_cmd_action(line);
562  }
563  } while (next > 0);
564 
565  return NULL;
566 }
567 
568 int start_cli_thread(pthread_t *cli_thread) {
569  int err;
570  err = pthread_create(cli_thread, NULL, cli_loop, NULL);
571  if (err != 0) {
572  debug("ERROR: can't create thread :[%s]", strerror(err));
573  } else {
574  debug("CLI Thread created successfully");
575  }
576  return err;
577 }
#define NEXT_ARG(arg, args)
Definition: cli.c:78
int n_routes
The routes that an MSU can send to.
Definition: dfg.h:120
int * msu_ids
Definition: scheduling.h:27
Interface for general-purpose socket communication.
int n_msus
The number of MSUs in dedos_dfg::msus.
Definition: dfg.h:255
int(* action)(char *)
Definition: cli.c:58
#define debug(fmt,...)
Definition: logging.h:78
struct dfg_scheduling scheduling
Information about where an MSU is scheduled.
Definition: dfg.h:225
static int parse_show_msus(char *args)
Definition: cli.c:142
struct dfg_route * get_dfg_route(unsigned int id)
Returns the route with the given ID.
Definition: dfg.c:76
uint8_t vertex_type
Whether the MSU is #ENTRY, #EXIT, or possible #ENTRY | #EXIT.
Definition: dfg.h:218
#define HELP_PREAMBLE
Definition: cli.c:48
static int parse_unclone_msu(char *args)
Definition: cli.c:377
struct dfg_msu * clone_msu(int msu_id)
Clone a msu of given ID.
Definition: scheduling.c:619
#define NOSTYLE
Definition: cli.c:46
static int route(struct msu_type *type, struct local_msu *sender, struct msu_msg *msg, struct msu_endpoint *output)
Definition: baremetal_msu.c:30
struct dfg_runtime * get_dfg_runtime(unsigned int runtime_id)
Returns the runtime with the given ID.
Definition: dfg.c:64
#define UL
Definition: cli.c:45
static int parse_show_routes(char *args)
Definition: cli.c:398
char name[32]
A name describing the function of the MSU.
Definition: dfg.h:179
static int parse_load_cfg(char *args)
Definition: cli.c:333
int id
Unique identifier for the runtime.
Definition: dfg.h:74
int add_endpoint(unsigned int msu_id, uint32_t key, unsigned int route_id)
Definition: api.c:177
Logging of status messages to the terminal.
struct dfg_msu_type * type
The type of the MSU and meta-routing information.
Definition: dfg.h:221
Representation of a runtime in the DFG.
Definition: dfg.h:73
Definition: cli.c:56
static int parse_del_msu(char *args)
Definition: cli.c:216
static void * cli_loop()
Definition: cli.c:546
struct dfg_route_endpoint * endpoints[256]
The endpoints of the route.
Definition: dfg.h:156
static int parse_show_stats(char *args)
Display controller's time series for a given msu.
Definition: cli.c:127
int n_endpoints
The number of endpoints in dfg_route::endpoints.
Definition: dfg.h:157
struct dfg_runtime * runtime
The runtime on which an MSU is running.
Definition: dfg.h:117
static int parse_del_route(char *args)
Definition: cli.c:244
int n_runtimes
The number of elements in dedos_dfg::runtimes.
Definition: dfg.h:260
int remove_msu(unsigned int id)
Definition: api.c:79
#define log_error(fmt,...)
Definition: logging.h:101
struct dfg_msu * msu
The MSU at this endpoint to which a message would be delivered.
Definition: dfg.h:143
static int parse_del_endpoint(char *args)
Definition: cli.c:278
#define MAX_INIT_DATA_LEN
The maximum length of the initial data that may be passed to an MSU.
Definition: dfg.h:53
static int parse_add_route(char *args)
Definition: cli.c:229
int id
A unique identifier for the MSU.
Definition: dfg.h:217
static int parse_show_route(char *args)
Definition: cli.c:417
struct dfg_thread * thread
The thread on which an MSU is running.
Definition: dfg.h:118
int id
Unique identifier for the thread.
Definition: dfg.h:105
Representation of a single MSU in the dfg.
Definition: dfg.h:216
static int parse_show_runtimes(char *args)
Definition: cli.c:64
int del_endpoint(unsigned int msu_id, unsigned int route_id)
Definition: api.c:206
int start_cli_thread(pthread_t *cli_thread)
Definition: cli.c:568
int add_route_to_msu(unsigned int msu_id, unsigned int route_id)
Definition: api.c:147
char cmd[32]
Definition: cli.c:57
#define MAX_MSU
The maximum number of MSUs which can be present in the system at a time.
Definition: dfg.h:39
int id
A unique identifier for the MSU type.
Definition: dfg.h:177
int runtime_fd(unsigned int runtime_id)
int id
A unique identifier for the route.
Definition: dfg.h:153
Defines a type of MSU.
Definition: msu_type.h:46
struct dfg_route * routes[32]
Definition: dfg.h:119
Top-level structure holding the data-flow graph.
Definition: dfg.h:239
A route through which MSU messages can be passed.
Definition: dfg.h:152
static struct dedos_dfg * dfg
Static local copy of the DFG, so each call doesn't have to pass a copy.
Definition: dfg.c:32
struct msu_init_data init_data
Initial data passed to the MSU.
Definition: dfg.h:219
static int parse_help(char *cmd)
Definition: cli.c:534
Interfaces for the creation and modification of the data-flow-graph and and general description of th...
static int parse_add_msu(char *args)
Definition: cli.c:175
static int parse_create_thread(char *args)
Definition: cli.c:313
struct dfg_msu * get_dfg_msu(unsigned int id)
Returns the MSU with the given ID.
Definition: dfg.c:86
int add_msu(unsigned int msu_id, unsigned int type_id, char *init_data_c, char *msu_mode, char *vertex_type_c, unsigned int thread_id, unsigned int runtime_id)
Definition: api.c:35
pthread_t cli_thread
Definition: main.c:42
struct dfg_runtime * runtimes[16]
The runtimes present in the application.
Definition: dfg.h:258
A single endpoint for an MSU route.
Definition: dfg.h:139
uint32_t key
The key associated with this endpoint.
Definition: dfg.h:140
char help[256]
Definition: cli.c:60
struct cmd_action cmd_actions[]
Definition: cli.c:439
static int runtime_id(int runtime_fd)
unsigned int uint32_t
Definition: uthash.h:96
static int parse_allocate()
//FIXME: broken behavior since dfg_vertex members are not pointers anymore Get a list of all MSU not ...
Definition: cli.c:90
struct dedos_dfg * get_dfg()
Definition: runtime_dfg.c:115
static int parse_add_endpoint(char *args)
Definition: cli.c:260
int create_worker_thread(unsigned int thread_id, enum blocking_mode mode)
Starts a new worker thread with the given thread ID and pinned/unpinned status.
int mod_endpoint(unsigned int msu_id, uint32_t key, unsigned int route_id)
Definition: api.c:234
int parse_cmd_action(char *cmd)
Definition: cli.c:506
static int parse_mod_endpoint(char *args)
Definition: cli.c:293
static int parse_clone_msu(char *args)
Definition: cli.c:358
char args[32][16]
Definition: cli.c:59
void show_stats(struct dfg_msu *msu)
#define BLD
Definition: cli.c:44
int unclone_msu(int msu_id)
Definition: scheduling.c:566
struct dfg_msu_type * msu_type
The type of MSU to which this route delivers.
Definition: dfg.h:155
struct dfg_msu * msus[512]
The MSUs present in the application.
Definition: dfg.h:253