· 4 years ago · Apr 30, 2021, 01:06 AM
1/*
2 * cli.c (Command line handler for the GINI router)
3 * This file contains the functions that implement the CLI.
4 * AUTHOR: Original version written by Weiling Xu
5 * Revised by Muthucumaru Maheswaran
6 * DATE: Revised on December 24, 2004
7 *
8 * The CLI is used as a configuration file parser
9 * as well. Right now the CLI module is only capable
10 * of parsing a very simple format and limited command set...
11 * Future development should make the CLI more versatile?
12 * The CLI defers unknown command to the UNIX system at this point.
13 */
14//#include "rdpstop.h"
15#include "udp.h"
16#include "tcp.h"
17#include "tcp_impl.h"
18#include "memp.h"
19#include "helpdefs.h"
20#include "cli.h"
21#include "gnet.h"
22#include "icmp.h"
23#include "grouter.h"
24#include <stdio.h>
25#include <strings.h>
26#include "grouter.h"
27#include "routetable.h"
28#include "mtu.h"
29#include "message.h"
30#include "classifier.h"
31#include "filter.h"
32#include "classspec.h"
33#include "packetcore.h"
34#include <slack/err.h>
35#include <slack/std.h>
36#include <slack/prog.h>
37#include <slack/err.h>
38#include <stdlib.h>
39#include <readline/readline.h>
40#include <readline/history.h>
41#include "openflow_flowtable.h"
42#include <limits.h>
43#include <unistd.h>
44#include <stdbool.h>
45
46
47Map *cli_map;
48Mapper *cli_mapper;
49static char *cur_line = (char *)NULL; // static variable for holding the line
50
51extern FILE *rl_instream;
52extern router_config rconfig;
53
54extern route_entry_t route_tbl[MAX_ROUTES];
55extern mtu_entry_t MTU_tbl[MAX_MTU];
56extern classlist_t *classifier;
57extern filtertab_t *filter;
58extern pktcore_t *pcore;
59
60/*
61 * This is the main routine of the CLI. Everything starts here.
62 * The CLI registers and commands into a hash table and forks a thread to
63 * handle the command line.
64 */
65int CLIInit(router_config *rarg)
66{
67
68 int stat, *jstat;
69
70 if (!(cli_map = map_create(free)))
71 return EXIT_FAILURE;
72
73 /*
74 * Disable certain signals such as Ctrl+C.. make the shell a little stable
75 */
76 redefineSignalHandler(SIGINT, dummyFunction);
77 redefineSignalHandler(SIGQUIT, dummyFunction);
78 redefineSignalHandler(SIGTSTP, dummyFunction);
79
80 verbose(2, "[cliHandler]:: Registering CLI commands in the command table ");
81 /*
82 * Register the commands allowed in the CLI. Each command is implemented by a
83 * function. The function is inserted into the command registary and picked up
84 * when the leading string is typed in the CLI.
85 */
86 registerCLI("help", helpCmd, SHELP_HELP, USAGE_HELP, LHELP_HELP); // Check
87 registerCLI("version", versionCmd, SHELP_VERSION, USAGE_VERSION, LHELP_VERSION); // Check
88 registerCLI("set", setCmd, SHELP_SET, USAGE_SET, LHELP_SET); // Check
89 registerCLI("get", getCmd, SHELP_GET, USAGE_GET, LHELP_GET); // Check
90 registerCLI("source", sourceCmd, SHELP_SOURCE, USAGE_SOURCE, LHELP_SOURCE); // Check
91 registerCLI("ifconfig", ifconfigCmd, SHELP_IFCONFIG, USAGE_IFCONFIG, LHELP_IFCONFIG);
92 registerCLI("route", routeCmd, SHELP_ROUTE, USAGE_ROUTE, LHELP_ROUTE);
93 registerCLI("arp", arpCmd, SHELP_ARP, USAGE_ARP, LHELP_ARP);
94 registerCLI("ping", pingCmd, SHELP_PING, USAGE_PING, LHELP_PING); // Check
95 registerCLI("console", consoleCmd, SHELP_CONSOLE, USAGE_CONSOLE, LHELP_CONSOLE); // Check
96 registerCLI("halt", haltCmd, SHELP_HALT, USAGE_HALT, LHELP_HALT); // Check
97 registerCLI("exit", haltCmd, SHELP_EXIT, USAGE_EXIT, LHELP_EXIT); // Check
98 registerCLI("queue", queueCmd, SHELP_QUEUE, USAGE_QUEUE, LHELP_QUEUE); // Check
99 registerCLI("qdisc", qdiscCmd, SHELP_QDISC, USAGE_QDISC, LHELP_QDISC); // Check
100 registerCLI("spolicy", spolicyCmd, SHELP_SPOLICY, USAGE_SPOLICY, LHELP_SPOLICY); // Check
101 registerCLI("class", classCmd, SHELP_CLASS, USAGE_CLASS, LHELP_CLASS);
102 registerCLI("filter", filterCmd, SHELP_FILTER, USAGE_FILTER, LHELP_FILTER);
103 registerCLI("openflow", openflowCmd, SHELP_OPENFLOW, USAGE_OPENFLOW, LHELP_OPENFLOW);
104 registerCLI("gnc", gncCmd, SHELP_GNC, USAGE_GNC, LHELP_GNC);
105
106 if (rarg->config_dir != NULL)
107 chdir(rarg->config_dir); // change to the configuration directory
108 if (rarg->config_file != NULL)
109 {
110 FILE *ifile = fopen(rarg->config_file, "r");
111 rl_instream = ifile;
112 CLIProcessCmds(ifile, 0);
113 rl_instream = stdin;
114 }
115
116 if (rarg->cli_flag != 0)
117 stat = pthread_create((pthread_t *)(&(rarg->clihandler)), NULL, CLIProcessCmdsInteractive, (void *)stdin);
118
119 pthread_join(rarg->clihandler, (void **)&jstat);
120 verbose(2, "[cliHandler]:: Destroying the CLI datastructures ");
121 CLIDestroy();
122}
123
124
125
126/*
127 * This function is called by the thread that is spawned to handle the CLI.
128 * It reads the console and invokes the handlers to process the commands typed
129 * by the user at the GINI router.
130 */
131
132void *CLIProcessCmdsInteractive(void *arg)
133{
134 FILE *fp = (FILE *)arg;
135
136 CLIPrintHelpPreamble();
137 CLIProcessCmds(fp, 1);
138}
139
140
141
142/*
143 * managing the signals: first an ignore function.
144 */
145void dummyFunction(int sign)
146{
147 printf("Signal [%d] is ignored \n", sign);
148}
149
150
151
152void parseACLICmd(char *str)
153{
154 char *token;
155 cli_entry_t *clie;
156 char orig_str[MAX_TMPBUF_LEN];
157
158 strcpy(orig_str, str);
159 token = strtok(str, " \n");
160 if ((clie = map_get(cli_map, token)) != NULL)
161 clie->handler((void *)clie);
162 else
163 {
164 printf("WARNING: %s not a gRouter command (deferring to Linux)\n", token);
165 system(orig_str);
166 }
167}
168
169
170void CLIPrintHelpPreamble()
171{
172 printf("\nGINI Router Shell, version: %s", prog_version());
173 printf("\n%s\n", HELP_PREAMPLE);
174}
175
176
177void CLIPrintHelp() {
178 cli_entry_t *clie;
179
180 CLIPrintHelpPreamble();
181 if (!(cli_mapper = mapper_create(cli_map)))
182 {
183 map_destroy(&cli_map);
184 return;
185 }
186 while (mapper_has_next(cli_mapper) == 1)
187 {
188
189 const Mapping *cli_mapping = mapper_next_mapping(cli_mapper);
190
191 clie = (cli_entry_t *) mapping_value(cli_mapping);
192 printf("%s:: \t%s\n\t%s\n", clie->keystr, clie->usagestr,
193 clie->short_helpstr);
194 }
195
196}
197
198
199/*
200 * Read a string, and return a pointer to it.
201 * Returns NULL on EOF.
202 */
203char *rlGets(int online)
204{
205 char prompt[MAX_TMPBUF_LEN];
206
207 if (cur_line != NULL)
208 {
209 free (cur_line);
210 cur_line = (char *)NULL;
211 }
212
213 sprintf(prompt, "GINI-%s $ ", rconfig.router_name);
214
215 do
216 {
217 // Get a line from the user.
218 cur_line = readline(prompt);
219 } while (online && (cur_line == NULL));
220
221 // If the line has any text in it,
222 // save it on the history.
223 if (cur_line && *cur_line)
224 add_history (cur_line);
225
226 return (cur_line);
227}
228
229
230
231/*
232 * process CLI. The file pointer fp already points to an open stream. The
233 * boolean variable online indicates whether processCLI is operating with
234 * a terminal or from a batch input. For batch input, it should be FALSE.
235 */
236
237void CLIProcessCmds(FILE *fp, int online)
238{
239 int state = PROGRAM;
240 char full_line[MAX_BUF_LEN];
241 int lineno = 0;
242 full_line[0] = '\0';
243
244 // NOTE: the input stream for readline is already redirected
245 // when processCLI is called from the "source" command.
246 while ((cur_line = rlGets(online)) != NULL)
247 {
248 switch (state)
249 {
250 case PROGRAM:
251 if (cur_line[0] == CARRIAGE_RETURN)
252 break;
253 if (cur_line[0] == LINE_FEED)
254 break;
255 if (cur_line[0] == COMMENT_CHAR)
256 state = COMMENT;
257 else if ((strlen(cur_line) > 2) && (cur_line[strlen(cur_line)-2] == CONTINUE_CHAR))
258 {
259 state = JOIN;
260 strcat(full_line, cur_line);
261 }
262 else
263 {
264 strcat(full_line, cur_line);
265 if (strlen(full_line) > 0)
266 parseACLICmd(full_line);
267 full_line[0] = '\0';
268 }
269 lineno++;
270 break;
271 case JOIN:
272 full_line[strlen(full_line)-2] = '\0';
273 if (cur_line[strlen(cur_line)-2] == CONTINUE_CHAR)
274 strcat(full_line, cur_line);
275 else
276 {
277 state = PROGRAM;
278 strcat(full_line, cur_line);
279 if (strlen(full_line) > 0)
280 parseACLICmd(full_line);
281 full_line[0] = '\0';
282 }
283 break;
284 case COMMENT:
285 if (cur_line[0] != COMMENT_CHAR)
286 {
287 if (cur_line[strlen(cur_line)-2] == CONTINUE_CHAR)
288 {
289 state = JOIN;
290 strcat(full_line, cur_line);
291 } else
292 {
293 state = PROGRAM;
294 strcat(full_line, cur_line);
295 if (strlen(full_line) > 0)
296 parseACLICmd(full_line);
297 full_line[0] = '\0';
298 }
299 }
300 break;
301 lineno++;
302 }
303 }
304}
305
306
307
308
309void CLIDestroy()
310{
311 mapper_destroy(&cli_mapper);
312 map_destroy(&cli_map);
313}
314
315
316void registerCLI(char *key, void (*handler)(),
317 char *shelp, char *usage, char *lhelp)
318{
319 cli_entry_t *clie = (cli_entry_t *) malloc(sizeof(cli_entry_t));
320
321 clie->handler = handler;
322 strcpy(clie->long_helpstr, lhelp);
323 strcpy(clie->usagestr, usage);
324 strcpy(clie->short_helpstr, shelp);
325 strcpy(clie->keystr, key);
326
327 verbose(2, "adding command %s.. to cli map ", key);
328 map_add(cli_map, key, clie);
329
330}
331
332
333/*------------------------------------------------------------------
334 * C L I H A N D L E R S
335 *-----------------------------------------------------------------*/
336
337
338// some macro defintions...
339#define GET_NEXT_PARAMETER(X, Y) if (((next_tok = strtok(NULL, " \n")) == NULL) || \
340 (strcmp(next_tok, X) != 0)) { error(Y); return; }; \
341 next_tok = strtok(NULL, " \n")
342#define GET_THIS_PARAMETER(X, Y) if (((next_tok = strtok(NULL, " \n")) == NULL) || \
343 (strstr(next_tok, X) == NULL)) { error(Y); return; }
344#define GET_THIS_OR_THIS_PARAMETER(X, Z, Y) if (((next_tok = strtok(NULL, " \n")) == NULL) || \
345 ((strstr(next_tok, X) == NULL) && \
346 (strstr(next_tok, Z) == NULL))) { error(Y); return; }
347
348int getDevType(char *str)
349{
350
351 if (strstr(str, "eth") != NULL)
352 return ETH_DEV;
353 if (strstr(str, "tap") != NULL)
354 return TAP_DEV;
355}
356
357
358/*
359 * Handler for the interface configuration command:
360 * ifconfig add eth1 -socket socketfile -addr IP_addr -hwaddr MAC [-gateway GW] [-mtu N]
361 * ifconfig add raw1 -bridge bridgeid -addr IP_addr
362 * ifconfig add tap0 -device dev_location -addr IP_addr -hwaddr MAC
363 * ifconfig add tun0 -dstip dst_ip -dstport portnum -addr IP_addr -hwaddr MAC
364 * ifconfig del eth0|tap0
365 * ifconfig show [brief|verbose]
366 * ifconfig up eth0|tap0
367 * ifconfig down eth0|tap0
368 * ifconfig mod eth0 (-gateway GW | -mtu N)
369 */
370void ifconfigCmd()
371{
372 char *next_tok;
373 interface_t *iface;
374 char dev_name[MAX_DNAME_LEN], con_sock[MAX_NAME_LEN], dev_type[MAX_NAME_LEN], raw_bridge[MAX_NAME_LEN];
375 uchar mac_addr[6], ip_addr[4], gw_addr[4], dst_ip[4];
376 int mtu, interface, mode;
377 short int dst_port;
378
379 // set default values for optional parameters
380 bzero(gw_addr, 4);
381 mtu = DEFAULT_MTU;
382 mode = NORMAL_LISTING;
383
384 // we have already matched ifconfig... now parsing rest of the parameters.
385 next_tok = strtok(NULL, " \n");
386
387 if (next_tok == NULL)
388 {
389 printf("[ifconfigCmd]:: missing action parameter.. type help ifconfig for usage.\n");
390 return;
391 }
392 if (!strcmp(next_tok, "add"))
393 {
394
395 next_tok = strtok(NULL, " \n");
396
397 if ( (next_tok == NULL) || (findDeviceDriver(next_tok) == NULL) )
398 {
399 printf("ifconfig:: missing or invalid interface spec ..\n");
400 return;
401 }
402
403 strcpy(dev_name, next_tok);
404 sscanf(dev_name, "%[a-z]", dev_type);
405 interface = gAtoi(dev_name);
406
407 if ((interface == 0) && (strcmp(dev_type, "eth") == 0))
408 {
409 printf("[ifconfigCmd]:: device number 0 is reserved for tap - start from 1\n");
410 return;
411 }
412
413 if (strcmp(dev_type, "eth") == 0)
414 {
415 GET_NEXT_PARAMETER("-socket", "ifconfig:: missing -socket spec ..");
416 strcpy(con_sock, next_tok);
417 } else if(strcmp(dev_type, "tun") == 0)
418 {
419 GET_NEXT_PARAMETER("-dstip", "ifconfig:: missing -dstip spec ..");
420 Dot2IP(next_tok, dst_ip);
421 GET_NEXT_PARAMETER("-dstport", "ifconfig:: missing -dstport spec ..");
422 dst_port = (short int)atoi(next_tok);
423 } else if (strcmp(dev_type, "raw") == 0)
424 {
425 printf("Checking bridge \n");
426 GET_NEXT_PARAMETER("-bridge", "ifconfig:: missing -bridge spec ..");
427 strcpy(raw_bridge, next_tok);
428 }
429
430 GET_NEXT_PARAMETER("-addr", "ifconfig:: missing -addr spec ..");
431 Dot2IP(next_tok, ip_addr);
432
433 if (strcmp(dev_type, "raw") != 0) {
434 GET_NEXT_PARAMETER("-hwaddr", "ifconfig:: missing -hwaddr spec ..");
435 Colon2MAC(next_tok, mac_addr);
436 }
437
438 while ((next_tok = strtok(NULL, " \n")) != NULL)
439 if (!strcmp("-gateway", next_tok))
440 {
441 next_tok = strtok(NULL, " \n");
442 Dot2IP(next_tok, gw_addr);
443 } else if (!strcmp("-mtu", next_tok))
444 {
445 next_tok = strtok(NULL, " \n");
446 mtu = atoi(next_tok);
447 }
448
449 if (strcmp(dev_type, "eth") == 0)
450 iface = GNETMakeEthInterface(con_sock, dev_name, mac_addr, ip_addr, mtu, 0);
451 else if (strcmp(dev_type, "tap") == 0)
452 iface = GNETMakeTapInterface(dev_name, mac_addr, ip_addr);
453 else if (strcmp(dev_type, "tun") == 0)
454 iface = GNETMakeTunInterface(dev_name, mac_addr, ip_addr, dst_ip, dst_port);
455 else if (strcmp(dev_type, "raw") == 0)
456 iface = GNETMakeRawInterface(dev_name, ip_addr, raw_bridge);
457 else {
458 printf("[ifconfigCmd]:: Unkown device type %s\n", dev_type);
459 return;
460 }
461
462 if (iface != NULL)
463 {
464 verbose(2, "[configureInterfaces]:: Inserting the definition in the interface table ");
465 GNETInsertInterface(iface);
466 addMTUEntry(MTU_tbl, iface->interface_id, iface->device_mtu, iface->ip_addr);
467 // for tap0 interface the MTU value cannot be changed. should we allow change?
468 }
469 }
470 else if (!strcmp(next_tok, "del"))
471 {
472 GET_THIS_OR_THIS_PARAMETER("eth", "tap", "ifconfig:: missing interface spec ..");
473 strcpy(dev_name, next_tok);
474 interface = gAtoi(next_tok);
475 destroyInterfaceByIndex(interface);
476 deleteMTUEntry(MTU_tbl, interface);
477 }
478 else if (!strcmp(next_tok, "up"))
479 {
480 GET_THIS_OR_THIS_PARAMETER("eth", "tap", "ifconfig:: missing interface spec ..");
481 strcpy(dev_name, next_tok);
482 interface = gAtoi(next_tok);
483 upInterface(interface);
484
485 }
486 else if (!strcmp(next_tok, "down"))
487 {
488 GET_THIS_OR_THIS_PARAMETER("eth", "tap", "ifconfig:: missing interface spec ..");
489 strcpy(dev_name, next_tok);
490 interface = gAtoi(next_tok);
491 downInterface(interface);
492 }
493 else if (!strcmp(next_tok, "mod"))
494 {
495 GET_THIS_PARAMETER("eth", "ifconfig:: missing interface spec ..");
496 strcpy(dev_name, next_tok);
497 interface = gAtoi(next_tok);
498
499 while ((next_tok = strtok(NULL, " \n")) != NULL)
500 if (!strcmp("-gateway", next_tok))
501 {
502 next_tok = strtok(NULL, " \n");
503 strcpy(gw_addr, next_tok);
504 } else if (!strcmp("-mtu", next_tok))
505 {
506 next_tok = strtok(NULL, " \n");
507 mtu = atoi(next_tok);
508 }
509
510 changeInterfaceMTU(interface, mtu);
511 }
512 else if (!strcmp(next_tok, "show"))
513 {
514 if ((next_tok = strtok(NULL, " \n")) != NULL)
515 {
516 if (strstr(next_tok, "bri") != NULL)
517 mode = BRIEF_LISTING;
518 else if (strstr(next_tok, "verb") != NULL)
519 mode = VERBOSE_LISTING;
520 } else
521 mode = NORMAL_LISTING;
522
523 printInterfaces(mode);
524 }
525 return;
526}
527
528
529/*
530 * Handler for the connection "route" command
531 * route show
532 * route add -dev eth0|tap0 -net nw_addr -netmask mask [-gw gw_addr]
533 * route del route_number
534 */
535void routeCmd()
536{
537 char *next_tok;
538 char tmpbuf[MAX_TMPBUF_LEN];
539 uchar net_addr[4], net_mask[4], nxth_addr[4];
540 int interface, del_route;
541 char dev_name[MAX_DNAME_LEN];
542
543 // set defaults for optional parameters
544 bzero(nxth_addr, 4);
545
546 next_tok = strtok(NULL, " \n");
547
548 if (next_tok != NULL)
549 {
550 if (!strcmp(next_tok, "add"))
551 {
552 GET_NEXT_PARAMETER("-dev", "route:: missing device name ..");
553 strcpy(dev_name, next_tok);
554 interface = gAtoi(next_tok);
555
556 GET_NEXT_PARAMETER("-net", "route:: missing network address ..");
557 Dot2IP(next_tok, net_addr);
558
559 GET_NEXT_PARAMETER("-netmask", "route:: missing netmask ..");
560 Dot2IP(next_tok, net_mask);
561
562 verbose(2, "[routeCmd]:: Device %s Interface %d, net_addr %s, netmask %s ",
563 dev_name, interface, IP2Dot(tmpbuf, net_addr), IP2Dot((tmpbuf+20), net_mask));
564
565 if (((next_tok = strtok(NULL, " \n")) != NULL) &&
566 (!strcmp("-gw", next_tok)))
567 {
568 next_tok = strtok(NULL, " \n");
569 Dot2IP(next_tok, nxth_addr);
570 }
571 addRouteEntry(route_tbl, net_addr, net_mask, nxth_addr, interface);
572 }
573 else if (!strcmp(next_tok, "del"))
574 {
575 next_tok = strtok(NULL, " \n");
576 del_route = gAtoi(next_tok);
577 deleteRouteEntryByIndex(route_tbl, del_route);
578 }
579 else if (!strcmp(next_tok, "show"))
580 printRouteTable(route_tbl);
581 }
582 return;
583}
584
585/*
586 * retreive next argument
587 * print error if no next argument exists
588 */
589char* next_arg(char* delim) {
590 char *next_tok;
591 next_tok = strtok(NULL, delim);
592 if (next_tok == NULL) {
593 printf("[gncCmd]:: incorrect arguments.. type help gnc for usage\n");
594 }
595 return next_tok;
596}
597/*
598 * callback function for UDP packets received
599 */
600void udp_recv_callback(void *arg, struct udp_pcb *pcb, struct pbuf *p, uchar *addr, uint16_t port) {
601 rdp_rcv(arg, pcb, p, addr, port);
602 /*bool check = rdp_rcv(arg, pcb, p, addr, port);
603 if(check)
604 printf("%s", (char*)p->payload);
605 uchar ipaddr_network_order[4];
606 gHtonl(ipaddr_network_order, addr);
607 udp_connect(arg, ipaddr_network_order, port); */
608}
609
610/*
611 * callback function for TCP packets received
612 */
613err_t tcp_recv_callback(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) {
614 printf("%s", (char*) p->payload);
615 return err;
616}
617
618// global variable for pcb of an established TCP connection
619struct tcp_pcb * pcb_established;
620
621/*
622 * call back function for TCP connection successful
623 */
624err_t tcp_accept_callback(void *arg, struct tcp_pcb *tpcb, err_t err) {
625 pcb_established = tpcb;
626 tcp_recv(tpcb, tcp_recv_callback);
627 return err;
628}
629
630// state information specifying that gnc command should be terminated
631// this is set to true if ^C (SIGINT) is received
632bool gncTerm = false;
633
634/*
635 * callback function for ^C (SIGINT) to specify that gnc should terminate
636 */
637void gncTerminate() {
638 gncTerm = true;
639}
640
641/*
642 * Handler for the "gnc" command:
643 * gnc [-u] <host> <port> // initiate a connection to a remote host
644 * gnc [-u] -l <port> // listen for an incoming connection from a remote host
645 */
646void gncCmd() {
647
648 // initialize LWIP code
649 memp_init();
650 pbuf_init();
651 udp_init();
652 tcp_init();
653
654 char *next_tok = next_arg(" \n");
655 if (next_tok == NULL)
656 return;
657
658 // TCP
659 if (strcmp(next_tok, "-u") != 0) {
660
661 // gnc -l <port>
662 if (!strcmp(next_tok, "-l")) {
663
664 // port
665 next_tok = next_arg(" \n");
666 if (next_tok == NULL)
667 return;
668 uint16_t port = atoi(next_tok);
669
670 // create and initialize pcb to listen to TCP connections at the specified port
671 struct tcp_pcb * pcb = tcp_new();
672 uchar any[4] = {0,0,0,0};
673 err_t err = tcp_bind(pcb, any, port);
674 pcb = tcp_listen(pcb);
675 tcp_accept(pcb, tcp_accept_callback);
676
677 // keep sending user input with the TCP connection
678 char payload[DEFAULT_MTU];
679 redefineSignalHandler(SIGINT, gncTerminate);
680 gncTerm = false;
681 while (!gncTerm) {
682 fgets(payload, sizeof(payload), stdin);
683 err_t e1 = tcp_write (pcb_established, payload, strlen(payload), TCP_WRITE_FLAG_MORE | TCP_WRITE_FLAG_COPY);
684 if (e1 != ERR_OK)
685 printf("tcp write error: %d\n", e1);
686 err_t e2 = tcp_output(pcb_established);
687 if (e1 != ERR_OK)
688 printf("tcp output error: %d\n", e2);
689 }
690
691 // reset SIGINT handler to ignore the signal
692 redefineSignalHandler(SIGINT, dummyFunctionCopy);
693
694 // remove and free pcb
695 tcp_shutdown(pcb, 1, 1);
696 }
697 // gnc <host> <port>
698 else {
699 // host
700 uchar ipaddr[4];
701 Dot2IP(next_tok, ipaddr);
702 gHtonl(ipaddr, ipaddr);
703
704 // port
705 next_tok = next_arg(" \n");
706 if (next_tok == NULL)
707 return;
708 u16_t port = atoi(next_tok);
709
710 // create and initialize pcb to make a TCP connection at the specified host and port
711 struct tcp_pcb * pcb = tcp_new();
712 err_t e0 = tcp_connect(pcb, ipaddr, port, NULL);
713 if (e0 != ERR_OK)
714 printf("tcp connect error: %d\n", e0);
715 tcp_recv(pcb, tcp_recv_callback);
716
717 // keep sending user input with the TCP connection
718 char payload[DEFAULT_MTU];
719 redefineSignalHandler(SIGINT, gncTerminate);
720 gncTerm = false;
721 while (!gncTerm) {
722 fgets(payload, sizeof(payload), stdin);
723 err_t e1 = tcp_write (pcb, payload, strlen(payload), TCP_WRITE_FLAG_MORE | TCP_WRITE_FLAG_COPY);
724 if (e1 != ERR_OK)
725 printf("tcp write error: %d\n", e1);
726 err_t e2 = tcp_output(pcb);
727 if (e2 != ERR_OK)
728 printf("tcp output error: %d\n", e2);
729 }
730
731 // reset SIGINT handler to ignore the signal
732 redefineSignalHandler(SIGINT, dummyFunctionCopy);
733
734 // remove and free pcb
735 err_t e3 = tcp_shutdown(pcb, 1, 1);
736 if (e3 != ERR_OK)
737 printf("shutdown err: %d\n", e3);
738 }
739 }
740
741 // -u for UDP
742 else {
743 char *next_tok = next_arg(" \n");
744 if (next_tok == NULL)
745 return;
746
747 // gnc -u -l <port>
748 if (!strcmp(next_tok, "-l")) {
749 // port
750 next_tok = next_arg(" \n");
751 if (next_tok == NULL)
752 return;
753 uint16_t port = atoi(next_tok);
754
755 // create and initialze pcb to listen to UDP connections at the specified port
756 struct udp_pcb * pcb = udp_new();
757 udp_recv(pcb, udp_recv_callback, pcb);
758 uchar any[4] = {0,0,0,0};
759 udp_bind(pcb, any, port);
760
761 // keep sending user input with the TCP connection
762 char payload[DEFAULT_MTU];
763 redefineSignalHandler(SIGINT, gncTerminate);
764 gncTerm = false;
765 while (!gncTerm) {
766 fgets(payload, sizeof(payload), stdin);
767
768 // create pbuf and call udp_send()
769 struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, strlen(payload), PBUF_RAM);
770 p->payload = payload;
771 err_t e1 = rdp_send(pcb, p);
772 if (e1 != ERR_OK)
773 printf("udp send error: %d\n", e1);
774 }
775
776 // reset SIGINT handler to ignore the signal
777 redefineSignalHandler(SIGINT, dummyFunctionCopy);
778
779 // remove and free pcb
780 udp_remove(pcb);
781 }
782
783 // gnc -u <host> <port>
784 else {
785 // host
786 uchar ipaddr[4];
787 Dot2IP(next_tok, ipaddr);
788
789 // port
790 next_tok = next_arg(" \n");
791 if (next_tok == NULL)
792 return;
793 uint16_t port = atoi(next_tok);
794
795 // create pcb and set its remote ip and remote port
796 struct udp_pcb * pcb = udp_new();
797 udp_connect(pcb, ipaddr, port);
798 udp_recv(pcb, udp_recv_callback, pcb);
799
800 // keep sending user input with the TCP connection
801 redefineSignalHandler(SIGINT, gncTerminate);
802 char payload[DEFAULT_MTU];
803 gncTerm = false;
804 while (!gncTerm) {
805 fgets(payload, sizeof(payload), stdin);
806
807 // create pbuf and call udp_send()
808 struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, strlen(payload), PBUF_RAM);
809 p->payload = payload;
810 err_t e1 = rdp_send(pcb, p);
811 if (e1 != ERR_OK)
812 printf("udp send error: %d\n", e1);
813 }
814
815 // reset SIGINT handler to ignore the signal
816 redefineSignalHandler(SIGINT, dummyFunctionCopy);
817
818 // remove and free pcb
819 udp_remove(pcb);
820
821 }
822 }
823}
824
825/*
826 * Handler for the connection "arp" command:
827 * arp show
828 * arp show -ip ip_addr
829 * arp del
830 * arp del -ip ip_addr
831 */
832void arpCmd()
833{
834 char *next_tok;
835 uchar mac_addr[6], ip_addr[4];
836
837 next_tok = strtok(NULL, " \n");
838
839 if (next_tok == NULL)
840 {
841 printf("[arpCmd]:: missing arp action.. type help arp for usage \n");
842 return;
843 }
844
845 if (!strcmp(next_tok, "show"))
846 ARPPrintTable();
847 else if (!strcmp(next_tok, "del"))
848 {
849 if ((next_tok = strtok(NULL, " \n")) != NULL)
850 {
851 if (!strcmp("-ip", next_tok))
852 {
853 next_tok = strtok(NULL, " \n");
854 Dot2IP(next_tok, ip_addr);
855 ARPDeleteEntry(ip_addr);
856 }
857 } else
858 ARPReInitTable();
859 } else if (!strcmp(next_tok, "add"))
860 {
861 if (!(next_tok = strtok(NULL, " \n")) || strcmp("-ip", next_tok))
862 return;
863 next_tok = strtok(NULL, " \n");
864 Dot2IP(next_tok, ip_addr);
865
866 if (!(next_tok = strtok(NULL, " \n")) || strcmp("-mac", next_tok))
867 return;
868 next_tok = strtok(NULL, " \n");
869 Colon2MAC(next_tok, mac_addr);
870 ARPAddEntry(ip_addr, mac_addr);
871 }
872}
873
874
875
876ip_spec_t *parseIPSpec(char *instr)
877{
878 ip_spec_t *ips;
879 char *ipaddr, *preflen;
880 char *str2, *ipnum;
881 char *saveptr, *saveptr2;
882 int i=4;
883
884 ips = (ip_spec_t *) malloc(sizeof(ip_spec_t));
885 bzero(ips, sizeof(ip_spec_t));
886
887 ipaddr = strtok_r(instr, " /", &saveptr);
888 preflen = strtok_r(NULL, " /", &saveptr);
889 if (preflen == NULL)
890 ips->preflen = 32;
891 else
892 ips->preflen = atoi(preflen);
893 for (str2 = ipaddr; i--; str2 = NULL)
894 {
895 ipnum = strtok_r(str2, ".", &saveptr2);
896 if (ipnum == NULL) break;
897
898 ips->ip_addr[i] = atoi(ipnum);
899 }
900
901 return ips;
902}
903
904
905port_range_t *parsePortRangeSpec(char *instr)
906{
907 port_range_t *prs;
908 char *savestr, *port;
909
910 prs = (port_range_t *) malloc(sizeof(port_range_t));
911 bzero(prs, sizeof(port_range_t));
912
913 port = strtok_r(instr, "-", &savestr);
914 prs->minport = atoi(port);
915
916 port = strtok_r(NULL, "-", &savestr);
917 prs->maxport = atoi(port);
918
919 return prs;
920}
921
922
923
924/*
925 * class add class_name [-src ( packet spec )] [-dst ( packet spec )]
926 * class del class_name
927 * class show
928 * packet_spec = -net ipaddr/prevlen -port lower-upper -prot number
929 */
930void classCmd()
931{
932 char *next_tok;
933 char tmpbuf[MAX_TMPBUF_LEN];
934 char cname[MAX_DNAME_LEN];
935 int sside;
936 ip_spec_t *ips;
937 port_range_t *pps;
938
939 next_tok = strtok(NULL, " \n");
940 if (next_tok != NULL)
941 {
942 if (!strcmp(next_tok, "add"))
943 {
944 next_tok = strtok(NULL, " \n");
945 strcpy(cname, next_tok);
946 addClassDef(classifier, cname);
947
948 while ((next_tok = strtok(NULL, " \n")) != NULL)
949 {
950 if (!strcmp(next_tok, "-src")) sside = 1;
951 if (!strcmp(next_tok, "-dst")) sside = 0;
952
953 while ((next_tok = strtok(NULL, "( )\n")) != NULL)
954 {
955 if (!strcmp(next_tok, "-net"))
956 {
957 next_tok = strtok(NULL, " )\n");
958 ips = parseIPSpec(next_tok);
959 insertIPSpec(classifier, cname, sside, ips);
960 }
961 if (!strcmp(next_tok, "-port"))
962 {
963 next_tok = strtok(NULL, " )\n");
964 pps = parsePortRangeSpec(next_tok);
965 insertPortRangeSpec(classifier, cname, sside, pps);
966 }
967 if (!strcmp(next_tok, "-prot"))
968 {
969 next_tok = strtok(NULL, " )\n");
970 insertProtSpec(classifier, cname, gAtoi(next_tok));
971 }
972 if (!strcmp(next_tok, "-tos"))
973 {
974 next_tok = strtok(NULL, " )\n");
975 insertTOSSpec(classifier, cname, gAtoi(next_tok));
976 }
977 }
978 }
979 }
980 else if (!strcmp(next_tok, "del"))
981 {
982 next_tok = strtok(NULL, " \n");
983 if (next_tok != NULL)
984 {
985 strcpy(cname, next_tok);
986 delClassDef(classifier, cname);
987 }
988 }
989 else if (!strcmp(next_tok, "show"))
990 printClassifier(classifier);
991 }
992 return;
993}
994
995
996
997
998/*
999 * filter add ( deny | allow ) class_name
1000 * filter move rule_number (up | down | top | bottom )
1001 * filter del rule_number
1002 * filter [on|off]
1003 * filter show
1004 * filter stats
1005 * filter flush
1006 */
1007void filterCmd()
1008{
1009 char *next_tok;
1010 char tmpbuf[MAX_TMPBUF_LEN];
1011 char cname[MAX_DNAME_LEN];
1012 int type, rulenum;
1013
1014
1015 next_tok = strtok(NULL, " \n");
1016 if (next_tok == NULL)
1017 printf("Filtering is %s\n", filter->filteron? "on" : "off");
1018 else
1019 {
1020 if (!strcmp(next_tok, "on"))
1021 filter->filteron = 1;
1022 else if (!strcmp(next_tok, "off"))
1023 filter->filteron = 0;
1024 else if (!strcmp(next_tok, "add"))
1025 {
1026 GET_THIS_OR_THIS_PARAMETER("deny", "allow", "deny | allow expected ");
1027 if (!strcmp(next_tok, "deny"))
1028 type = 0;
1029 else if (!strcmp(next_tok, "allow"))
1030 type = 1;
1031 else
1032 return;
1033 if ((next_tok = strtok(NULL, " \n")) != NULL)
1034 addFilterRule(filter, type, next_tok);
1035 }
1036 else if (!strcmp(next_tok, "move"))
1037 {
1038 if ((next_tok = strtok(NULL, " \n")) != NULL)
1039 {
1040 rulenum = atoi(next_tok);
1041 if ((rulenum < 0) || (rulenum >= filter->rulecnt))
1042 {
1043 printf("Invalid rule number %d \n", rulenum);
1044 return;
1045 }
1046 next_tok = strtok(NULL, " \n");
1047 moveRule(filter, rulenum, next_tok);
1048 }
1049 }
1050 else if (!strcmp(next_tok, "del"))
1051 {
1052 if ((next_tok = strtok(NULL, " \n")) != NULL)
1053 {
1054 rulenum = atoi(next_tok);
1055 if ((rulenum < 0) || (rulenum >= filter->rulecnt))
1056 {
1057 printf("Invalid rule number %d \n", rulenum);
1058 return;
1059 }
1060 delFilterRule(filter, rulenum);
1061 }
1062 }
1063 else if (!strcmp(next_tok, "show"))
1064 printFilter(filter);
1065 else if (!strcmp(next_tok, "stats"))
1066 printFilterStats(filter);
1067 else if (!strcmp(next_tok, "flush"))
1068 flushFilter(filter);
1069 }
1070}
1071
1072
1073
1074/*
1075 * prints the version number of the gRouter.
1076 * TODO: make this version number globally controlled variable that is
1077 * set by the installer.
1078 */
1079void versionCmd()
1080{
1081 printf("\nGINI Router Version: %s \n\n", prog_version());
1082 if (rconfig.openflow) {
1083 printf("\nOpenFlow 1.0 mode");
1084 }
1085 printf("\n\n");
1086}
1087
1088
1089
1090/*
1091 * halts the gRouter.
1092 * TODO: should we do any specific clean up of state before halting the router?
1093 */
1094void haltCmd()
1095{
1096 verbose(1, "[haltCmd]:: Router %s shutting down.. ", prog_name());
1097 raise(SIGUSR1);
1098}
1099
1100
1101/*
1102 * send a ping packet...
1103 * ping [-num] IP_addr [-size payload size]
1104 */
1105
1106void pingCmd()
1107{
1108 char *next_tok = strtok(NULL, " \n");
1109 int tries, pkt_size;
1110 uchar ip_addr[4];
1111 char tmpbuf[MAX_TMPBUF_LEN];
1112
1113 if (next_tok == NULL)
1114 return;
1115
1116 if (next_tok[0] == '-')
1117 {
1118 tries = gAtoi(next_tok);
1119 next_tok = strtok(NULL, " \n");
1120 } else
1121 tries = INT_MAX;
1122 Dot2IP(next_tok, ip_addr);
1123 verbose(2, "[pingCmd]:: ping command sent, tries = %d, IP = %s",
1124 tries, IP2Dot(tmpbuf, ip_addr));
1125
1126 if ((next_tok = strtok(NULL, " \n")) != NULL)
1127 {
1128 if (!strcmp(next_tok, "-size"))
1129 {
1130 next_tok = strtok(NULL, " \n");
1131 pkt_size = atoi(next_tok);
1132 } else
1133 pkt_size = 64;
1134 } else
1135 pkt_size = 64;
1136 ICMPDoPing(ip_addr, pkt_size, tries);
1137}
1138
1139
1140/*
1141 * set verbose [value]
1142 * set raw-time [true | false ]
1143 * set update-delay value
1144 * set sched-cycle value
1145 */
1146void setCmd()
1147{
1148 char *next_tok = strtok(NULL, " \n");
1149 int level, cyclelen, rawmode, updateinterval;
1150
1151 if (next_tok == NULL)
1152 error("[setCmd]:: ERROR!! missing set-parameter");
1153 else if (!strcmp(next_tok, "sched-cycle"))
1154 {
1155 if ((next_tok = strtok(NULL, " \n")) != NULL)
1156 {
1157 cyclelen = atoi(next_tok);
1158 if (cyclelen >=0)
1159 rconfig.schedcycle = cyclelen;
1160 else
1161 verbose(1, "ERROR!! schedule cycle length should be positive \n");
1162 } else
1163 printf("\nSchedule cycle length: %d (microseconds) \n", rconfig.schedcycle);
1164 } else if (!strcmp(next_tok, "verbose"))
1165 {
1166 if ((next_tok = strtok(NULL, " \n")) != NULL)
1167 {
1168 level = atoi(next_tok);
1169 if ((level >= 0) && (level <= 6))
1170 prog_set_verbosity_level(level);
1171 else
1172 verbose(1, "[setCmd]:: ERROR!! level should be in [0..6] \n");
1173 } else
1174 printf("\nVerbose level: %ld \n", prog_verbosity_level());
1175 } else if (!strcmp(next_tok, "raw-times"))
1176 {
1177 if ((next_tok = strtok(NULL, " \n")) != NULL)
1178 {
1179 rawmode = atoi(next_tok);
1180 if ((rawmode == 0) || (rawmode == 1))
1181 setTimeMode(rawmode);
1182 else
1183 printf("\nRaw time mode: %d \n", getTimeMode());
1184 }
1185 else if (!strcmp(next_tok, "update-delay"))
1186 {
1187 if ((next_tok = strtok(NULL, " \n")) != NULL)
1188 {
1189 updateinterval = atoi(next_tok);
1190 if (updateinterval >=2)
1191 setUpdateInterval(updateinterval);
1192 else
1193 verbose(1, "Invalid update interval.. setting failed.. \n");
1194 }
1195 else
1196 printf("Update interval: %d (seconds) \n", getUpdateInterval());
1197 }
1198 }
1199}
1200
1201
1202
1203void sourceCmd()
1204{
1205 FILE *fp;
1206 char *next_tok = strtok(NULL, " \n");
1207
1208 if (next_tok == NULL)
1209 {
1210 error("[sourceCmd]:: ERROR!! missing file specification...");
1211 return;
1212 }
1213
1214 if ((fp = fopen(next_tok, "r")) == NULL)
1215 {
1216 error("[sourceCmd]:: ERROR!! cannot open file %s.. ", next_tok);
1217 return;
1218 }
1219
1220 rl_instream = fp;
1221 CLIProcessCmds(fp, 0);
1222 rl_instream = stdin;
1223}
1224
1225
1226void consoleCmd()
1227{
1228 char *next_tok = strtok(NULL, " \n");
1229
1230 if (next_tok == NULL)
1231 consoleGetState();
1232 else if (!strcmp(next_tok, "restart"))
1233 consoleRestart(rconfig.config_dir, rconfig.router_name);
1234 else
1235 {
1236 verbose(2, "[consoleCmd]:: Unknown port action requested \n");
1237 return;
1238 }
1239}
1240
1241
1242/*
1243 * helpCmd - this implements the following command line.
1244 * help - prints a general help usage message
1245 * help command - prints the usage for the specified command
1246 * the last usage should also print an error if the command is unknown.
1247 */
1248
1249void helpCmd()
1250{
1251 char tmpbuf[MAX_TMPBUF_LEN];
1252 char *next_tok = strtok(NULL, " \n");
1253 cli_entry_t *n_clie;
1254
1255 if (next_tok == NULL)
1256 CLIPrintHelp();
1257 else
1258 {
1259 n_clie = (cli_entry_t *)map_get(cli_map, next_tok);
1260 if (n_clie == NULL)
1261 printf("ERROR! No help for command: %s \n", next_tok);
1262 else
1263 {
1264 if (strstr(n_clie->long_helpstr, ".hlp") != NULL)
1265 {
1266 sprintf(tmpbuf, "man %s/grouter/helpdefs/%s", getenv("GINI_SHARE"), n_clie->long_helpstr);
1267 system(tmpbuf);
1268 } else
1269 {
1270 printf("\n%s:: %s\n", n_clie->keystr, n_clie->usagestr);
1271 printf("%s\n", n_clie->long_helpstr);
1272 }
1273 }
1274 }
1275}
1276
1277/*
1278 * get parameter_name
1279 */
1280void getCmd()
1281{
1282 char *next_tok = strtok(NULL, " \n");
1283 int level, cyclelen, rawmode, updateinterval;
1284
1285 if (next_tok == NULL)
1286 error("[getCmd]:: ERROR!! missing get-parameter");
1287 else if (!strcmp(next_tok, "sched-cycle"))
1288 printf("\nSchedule cycle length: %d (microseconds) \n", rconfig.schedcycle);
1289 else if (!strcmp(next_tok, "verbose"))
1290 printf("\nVerbose level: %ld \n", prog_verbosity_level());
1291 else if (!strcmp(next_tok, "raw-times"))
1292 printf("\nRaw time mode: %d \n", getTimeMode());
1293 else if (!strcmp(next_tok, "update-delay"))
1294 printf("Update interval: %d (seconds) \n", getUpdateInterval());
1295}
1296
1297
1298
1299/*
1300 * queue add class_name qdisc_name [-size num_slots] [-weight value] [-delay delay_microsec]
1301 * queue show
1302 * queue del queue_number
1303 * queue mod queue_number [-weight value] [-delay delay_microsec]
1304 * queue stats [queue_number]
1305 */
1306void queueCmd()
1307{
1308 char *next_tok;
1309 char cname[MAX_DNAME_LEN], qdisc[MAX_DNAME_LEN];
1310 // the following parameters are set to default values which are sometimes overwritten
1311 int num_slots = 0; // means, set to default
1312 double weight = 1.0, delay = 2.0;
1313
1314
1315 if ((next_tok = strtok(NULL, " \n")) != NULL)
1316 {
1317 if (!strcmp(next_tok, "add"))
1318 {
1319 next_tok = strtok(NULL, " \n");
1320 strcpy(cname, next_tok);
1321 if (getClassDef(classifier, cname) == NULL)
1322 {
1323 verbose(1, "[queue]:: class name %s not defined ..", cname);
1324 return;
1325 }
1326 next_tok = strtok(NULL, " \n");
1327 strcpy(qdisc, next_tok);
1328 if (lookupQDisc(pcore->qdiscs, qdisc) < 0)
1329 {
1330 verbose(1, "[queue]:: qdisc %s not defined .. ", qdisc);
1331 return;
1332 }
1333
1334 while ((next_tok = strtok(NULL, " \n")) != NULL)
1335 {
1336 if (!strcmp(next_tok, "-size"))
1337 {
1338 next_tok = strtok(NULL, " \n");
1339 num_slots = atoi(next_tok);
1340 }
1341 else if (!strcmp(next_tok, "-weight"))
1342 {
1343 next_tok = strtok(NULL, " \n");
1344 weight = atof(next_tok);
1345 }
1346 else if (!strcmp(next_tok, "-delay"))
1347 {
1348 next_tok = strtok(NULL, " \n");
1349 delay = atof(next_tok);
1350 }
1351 }
1352 addPktCoreQueue(pcore, cname, qdisc, weight, delay, num_slots);
1353 }
1354 else if (!strcmp(next_tok, "show"))
1355 printAllQueues(pcore);
1356 else if (!strcmp(next_tok, "del"))
1357 {
1358 if ((next_tok = strtok(NULL, " \n")) != NULL)
1359 delPktCoreQueue(pcore, next_tok);
1360 }
1361 else if (!strcmp(next_tok, "mod"))
1362 {
1363 if ((next_tok = strtok(NULL, " \n")) != NULL)
1364 {
1365 strcpy(cname, next_tok);
1366 if ((next_tok = strtok(NULL, " \n")) != NULL)
1367 {
1368 if (!strcmp(next_tok, "-weight"))
1369 {
1370 next_tok = strtok(NULL, " \n");
1371 weight = atof(next_tok);
1372 modifyQueueWeight(pcore, cname, weight);
1373 }
1374 else if (!strcmp(next_tok, "-qdisc"))
1375 {
1376 next_tok = strtok(NULL, " \n");
1377 modifyQueueDiscipline(pcore, cname, next_tok);
1378 }
1379 }
1380 }
1381 }
1382 else if (!strcmp(next_tok, "stats"))
1383 printQueueStats(pcore);
1384 }
1385}
1386
1387
1388
1389/*
1390 * qdisc show
1391 * qdisc add taildrop
1392 * qdisc add droponfull
1393 * qdisc add dropfront
1394 * qdisc add red -min minval -max maxval -pmax pmaxval
1395 */
1396void qdiscCmd()
1397{
1398 char *next_tok = strtok(NULL, " \n");
1399 double pmax = 0.9;
1400 double minval = 0.0, maxval = 1.0;
1401
1402 if (!strcmp(next_tok, "show"))
1403 printQdiscs(pcore->qdiscs);
1404 else if (!strcmp(next_tok, "add"))
1405 {
1406 next_tok = strtok(NULL, " \n");
1407 if (!strcmp(next_tok, "red"))
1408 {
1409 while ((next_tok = strtok(NULL, " \n")) != NULL)
1410 {
1411 if (!strcmp(next_tok, "-min"))
1412 {
1413 next_tok = strtok(NULL, " \n");
1414 minval = atof(next_tok);
1415 }
1416 if (!strcmp(next_tok, "-max"))
1417 {
1418 next_tok = strtok(NULL, " \n");
1419 maxval = atof(next_tok);
1420 }
1421 if (!strcmp(next_tok, "-pmax"))
1422 {
1423 next_tok = strtok(NULL, " \n");
1424 pmax = atof(next_tok);
1425 }
1426 }
1427 addRED(pcore->qdiscs, minval, maxval, pmax);
1428 }
1429 }
1430}
1431
1432
1433
1434/*
1435 * spolicy show
1436 */
1437void spolicyCmd()
1438{
1439 char *next_tok = strtok(NULL, " \n");
1440
1441 if (!strcmp(next_tok, "show"))
1442 printf("Scheduling policy: rr (round robin)\n");
1443}
1444
1445void openflowCmd()
1446{
1447 if (!rconfig.openflow)
1448 {
1449 printf("OpenFlow not enabled\n");
1450 return;
1451 }
1452
1453 char *next_tok = strtok(NULL, " \n");
1454 if (next_tok != NULL && !strcmp(next_tok, "entry"))
1455 {
1456 next_tok = strtok(NULL, " \n");
1457 if (next_tok != NULL && !strcmp(next_tok, "all"))
1458 {
1459 openflow_flowtable_print_entries();
1460 return;
1461 }
1462 else if (next_tok != NULL) {
1463 char *endptr;
1464 uint32_t num = strtol(next_tok, &endptr, 10);
1465 if (endptr != next_tok)
1466 {
1467 openflow_flowtable_print_entry(num);
1468 return;
1469 }
1470 }
1471 }
1472 else if (next_tok != NULL && !strcmp(next_tok, "stats"))
1473 {
1474 next_tok = strtok(NULL, " \n");
1475 if (next_tok != NULL && !strcmp(next_tok, "desc"))
1476 {
1477 openflow_config_print_desc_stats();
1478 return;
1479 }
1480 else if (next_tok != NULL && !strcmp(next_tok, "entry"))
1481 {
1482 next_tok = strtok(NULL, " \n");
1483 if (next_tok != NULL && !strcmp(next_tok, "all"))
1484 {
1485 openflow_flowtable_print_entry_stats();
1486 return;
1487 }
1488 else if (next_tok != NULL)
1489 {
1490 char *endptr;
1491 uint32_t num = strtol(next_tok, &endptr, 10);
1492 if (endptr != next_tok)
1493 {
1494 openflow_flowtable_print_entry_stat(num);
1495 return;
1496 }
1497 }
1498 }
1499 else if (next_tok != NULL && !strcmp(next_tok, "table"))
1500 {
1501 openflow_flowtable_print_table_stats();
1502 return;
1503 }
1504 else if (next_tok != NULL && !strcmp(next_tok, "port"))
1505 {
1506 next_tok = strtok(NULL, " \n");
1507 if (next_tok != NULL && !strcmp(next_tok, "all"))
1508 {
1509 openflow_config_print_port_stats();
1510 return;
1511 }
1512 else if (next_tok != NULL) {
1513 char *endptr;
1514 uint32_t num = strtol(next_tok, &endptr, 10);
1515 if (endptr != next_tok)
1516 {
1517 openflow_config_print_port_stat(num);
1518 return;
1519 }
1520 }
1521 }
1522 }
1523 else if (next_tok != NULL && !strcmp(next_tok, "port"))
1524 {
1525 next_tok = strtok(NULL, " \n");
1526 if (next_tok != NULL && !strcmp(next_tok, "all"))
1527 {
1528 openflow_config_print_ports();
1529 return;
1530 }
1531 else if (next_tok != NULL) {
1532 char *endptr;
1533 uint32_t num = strtol(next_tok, &endptr, 10);
1534 if (endptr != next_tok)
1535 {
1536 openflow_config_print_port(num);
1537 return;
1538 }
1539 }
1540 }
1541 else if (next_tok != NULL && !strcmp(next_tok, "reconnect"))
1542 {
1543 openflow_ctrl_iface_reconnect();
1544 return;
1545 }
1546
1547 printf("Unrecognized OpenFlow command\n");
1548}
1549