]> git.proxmox.com Git - mirror_ovs.git/blame - lib/dpctl.c
dpctl: Export next argument to be parsed in opt_dpif_open().
[mirror_ovs.git] / lib / dpctl.c
CommitLineData
fceef209 1/*
a129fe8c 2 * Copyright (c) 2008-2017 Nicira, Inc.
fceef209
DDP
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <config.h>
b2befd5b
BP
18#include <sys/types.h>
19#include <netinet/in.h>
fceef209
DDP
20#include <arpa/inet.h>
21#include <errno.h>
22#include <inttypes.h>
23#include <sys/socket.h>
24#include <net/if.h>
fceef209
DDP
25#include <stdarg.h>
26#include <stdlib.h>
27#include <string.h>
28#include <unistd.h>
29
30#include "command-line.h"
31#include "compiler.h"
dffae65f 32#include "ct-dpif.h"
fceef209
DDP
33#include "dirs.h"
34#include "dpctl.h"
35#include "dpif.h"
3e8a2ad1 36#include "openvswitch/dynamic-string.h"
fceef209 37#include "flow.h"
e29747e4 38#include "openvswitch/match.h"
fceef209 39#include "netdev.h"
abb5943d 40#include "netdev-dpdk.h"
fceef209
DDP
41#include "netlink.h"
42#include "odp-util.h"
64c96779 43#include "openvswitch/ofpbuf.h"
fceef209 44#include "packets.h"
ee89ea7b 45#include "openvswitch/shash.h"
fceef209
DDP
46#include "simap.h"
47#include "smap.h"
48#include "sset.h"
49#include "timeval.h"
50#include "unixctl.h"
51#include "util.h"
0d71302e
BP
52#include "openvswitch/ofp-flow.h"
53#include "openvswitch/ofp-port.h"
d1fd1ea9
BP
54#include "openvswitch/vlog.h"
55VLOG_DEFINE_THIS_MODULE(dpctl);
fceef209 56
56cad666
AW
57typedef int dpctl_command_handler(int argc, const char *argv[],
58 struct dpctl_params *);
59struct dpctl_command {
60 const char *name;
61 const char *usage;
62 int min_args;
63 int max_args;
64 dpctl_command_handler *handler;
1f4a7252 65 enum { DP_RO, DP_RW} mode;
56cad666
AW
66};
67static const struct dpctl_command *get_all_dpctl_commands(void);
7521b9e5
DDP
68static void dpctl_print(struct dpctl_params *dpctl_p, const char *fmt, ...)
69 OVS_PRINTF_FORMAT(2, 3);
70static void dpctl_error(struct dpctl_params* dpctl_p, int err_no,
71 const char *fmt, ...)
72 OVS_PRINTF_FORMAT(3, 4);
56cad666 73
fceef209
DDP
74static void
75dpctl_puts(struct dpctl_params *dpctl_p, bool error, const char *string)
76{
77 dpctl_p->output(dpctl_p->aux, error, string);
78}
79
80static void
81dpctl_print(struct dpctl_params *dpctl_p, const char *fmt, ...)
82{
83 char *string;
84 va_list args;
85
86 va_start(args, fmt);
87 string = xvasprintf(fmt, args);
88 va_end(args);
89
90 dpctl_puts(dpctl_p, false, string);
91 free(string);
92}
93
94static void
95dpctl_error(struct dpctl_params* dpctl_p, int err_no, const char *fmt, ...)
96{
97 const char *subprogram_name = get_subprogram_name();
98 struct ds ds = DS_EMPTY_INITIALIZER;
99 int save_errno = errno;
100 va_list args;
101
102
103 if (subprogram_name[0]) {
104 ds_put_format(&ds, "%s(%s): ", program_name,subprogram_name);
105 } else {
106 ds_put_format(&ds, "%s: ", program_name);
107 }
108
109 va_start(args, fmt);
110 ds_put_format_valist(&ds, fmt, args);
111 va_end(args);
112
113 if (err_no != 0) {
114 ds_put_format(&ds, " (%s)", ovs_retval_to_string(err_no));
115 }
116 ds_put_cstr(&ds, "\n");
117
118 dpctl_puts(dpctl_p, true, ds_cstr(&ds));
119
120 ds_destroy(&ds);
121
122 errno = save_errno;
123}
124\f
125static int dpctl_add_if(int argc, const char *argv[], struct dpctl_params *);
126
127static int
128if_up(struct netdev *netdev)
129{
130 return netdev_turn_flags_on(netdev, NETDEV_UP, NULL);
131}
132
133/* Retrieve the name of the datapath if exactly one exists. The caller
0bd28b0b
JP
134 * is responsible for freeing the returned string. If a single datapath
135 * name cannot be determined, returns NULL. */
fceef209
DDP
136static char *
137get_one_dp(struct dpctl_params *dpctl_p)
138{
139 struct sset types;
140 const char *type;
141 char *dp_name = NULL;
142 size_t count = 0;
143
144 sset_init(&types);
145 dp_enumerate_types(&types);
146 SSET_FOR_EACH (type, &types) {
147 struct sset names;
148
149 sset_init(&names);
150 if (!dp_enumerate_names(type, &names)) {
151 count += sset_count(&names);
152 if (!dp_name && count == 1) {
153 dp_name = xasprintf("%s@%s", type, SSET_FIRST(&names));
154 }
155 }
156 sset_destroy(&names);
157 }
158 sset_destroy(&types);
159
160 if (!count) {
161 dpctl_error(dpctl_p, 0, "no datapaths exist");
162 } else if (count > 1) {
163 dpctl_error(dpctl_p, 0, "multiple datapaths, specify one");
164 free(dp_name);
165 dp_name = NULL;
166 }
167
168 return dp_name;
169}
170
171static int
172parsed_dpif_open(const char *arg_, bool create, struct dpif **dpifp)
173{
174 int result;
175 char *name, *type;
176
177 dp_parse_name(arg_, &name, &type);
178
179 if (create) {
180 result = dpif_create(name, type, dpifp);
181 } else {
182 result = dpif_open(name, type, dpifp);
183 }
184
185 free(name);
186 free(type);
187 return result;
188}
189
ffdcd110
DB
190static bool
191dp_exists(const char *queried_dp)
192{
193 char *queried_name, *queried_type;
194 dp_parse_name(queried_dp, &queried_name, &queried_type);
195 struct sset dpif_names = SSET_INITIALIZER(&dpif_names),
196 dpif_types = SSET_INITIALIZER(&dpif_types);
197 dp_enumerate_types(&dpif_types);
198
199 bool found = (sset_contains(&dpif_types, queried_type) &&
200 !dp_enumerate_names(queried_type, &dpif_names) &&
201 sset_contains(&dpif_names, queried_name));
202
203 sset_destroy(&dpif_names);
204 sset_destroy(&dpif_types);
205 return found;
206}
207
208static bool
209dp_arg_exists(int argc, const char *argv[])
210{
211 return argc > 1 && dp_exists(argv[1]);
212}
213
f33cdd7b
JP
214/* Open a dpif with an optional name argument.
215 *
ffdcd110
DB
216 * The datapath name is not a mandatory parameter for this command. If it is
217 * not specified, we retrieve it from the current setup, assuming only one
7cfb862c
YHW
218 * exists. On success stores the opened dpif in '*dpifp', and the next
219 * arugment to be parsed in '*indexp'. */
f33cdd7b
JP
220static int
221opt_dpif_open(int argc, const char *argv[], struct dpctl_params *dpctl_p,
7cfb862c 222 int max_args, struct dpif **dpifp, int *indexp)
f33cdd7b 223{
ffdcd110 224 char *dpname;
7cfb862c
YHW
225
226 if (indexp) {
227 *indexp = 1;
228 }
229
ffdcd110
DB
230 if (dp_arg_exists(argc, argv)) {
231 dpname = xstrdup(argv[1]);
7cfb862c
YHW
232 if (indexp) {
233 *indexp = 2;
234 }
ffdcd110
DB
235 } else if (argc != max_args) {
236 dpname = get_one_dp(dpctl_p);
237 } else {
238 /* If the arguments are the maximum possible number and there is no
239 * valid datapath argument, then we fall into the case of dpname is
240 * NULL, since this is an error. */
241 dpname = NULL;
242 }
243
f33cdd7b 244 int error = 0;
f33cdd7b
JP
245 if (!dpname) {
246 error = EINVAL;
247 dpctl_error(dpctl_p, error, "datapath not found");
248 } else {
249 error = parsed_dpif_open(dpname, false, dpifp);
250 free(dpname);
251 if (error) {
252 dpctl_error(dpctl_p, error, "opening datapath");
253 }
254 }
255 return error;
256}
257
fceef209
DDP
258static int
259dpctl_add_dp(int argc, const char *argv[],
260 struct dpctl_params *dpctl_p)
261{
262 struct dpif *dpif;
263 int error;
264
265 error = parsed_dpif_open(argv[1], true, &dpif);
266 if (error) {
267 dpctl_error(dpctl_p, error, "add_dp");
268 return error;
269 }
270 dpif_close(dpif);
271 if (argc > 2) {
272 error = dpctl_add_if(argc, argv, dpctl_p);
273 }
274 return error;
275}
276
277static int
278dpctl_del_dp(int argc OVS_UNUSED, const char *argv[],
279 struct dpctl_params *dpctl_p)
280{
281 struct dpif *dpif;
282 int error;
283
284 error = parsed_dpif_open(argv[1], false, &dpif);
285 if (error) {
286 dpctl_error(dpctl_p, error, "opening datapath");
287 return error;
288 }
289 error = dpif_delete(dpif);
290 if (error) {
291 dpctl_error(dpctl_p, error, "del_dp");
292 }
293
294 dpif_close(dpif);
295 return error;
296}
297
298static int
299dpctl_add_if(int argc OVS_UNUSED, const char *argv[],
300 struct dpctl_params *dpctl_p)
301{
302 struct dpif *dpif;
303 int i, error, lasterror = 0;
304
305 error = parsed_dpif_open(argv[1], false, &dpif);
306 if (error) {
307 dpctl_error(dpctl_p, error, "opening datapath");
308 return error;
309 }
310 for (i = 2; i < argc; i++) {
311 const char *name, *type;
312 char *save_ptr = NULL, *argcopy;
313 struct netdev *netdev = NULL;
314 struct smap args;
315 odp_port_t port_no = ODPP_NONE;
316 char *option;
317
318 argcopy = xstrdup(argv[i]);
319 name = strtok_r(argcopy, ",", &save_ptr);
320 type = "system";
321
322 if (!name) {
323 dpctl_error(dpctl_p, 0, "%s is not a valid network device name",
324 argv[i]);
325 error = EINVAL;
326 goto next;
327 }
328
329 smap_init(&args);
330 while ((option = strtok_r(NULL, ",", &save_ptr)) != NULL) {
331 char *save_ptr_2 = NULL;
332 char *key, *value;
333
334 key = strtok_r(option, "=", &save_ptr_2);
335 value = strtok_r(NULL, "", &save_ptr_2);
336 if (!value) {
337 value = "";
338 }
339
340 if (!strcmp(key, "type")) {
341 type = value;
342 } else if (!strcmp(key, "port_no")) {
343 port_no = u32_to_odp(atoi(value));
344 } else if (!smap_add_once(&args, key, value)) {
345 dpctl_error(dpctl_p, 0, "duplicate \"%s\" option", key);
346 }
347 }
348
349 error = netdev_open(name, type, &netdev);
350 if (error) {
351 dpctl_error(dpctl_p, error, "%s: failed to open network device",
352 name);
353 goto next_destroy_args;
354 }
355
356 error = netdev_set_config(netdev, &args, NULL);
357 if (error) {
358 goto next_destroy_args;
359 }
360
361 error = dpif_port_add(dpif, netdev, &port_no);
362 if (error) {
363 dpctl_error(dpctl_p, error, "adding %s to %s failed", name,
364 argv[1]);
365 goto next_destroy_args;
366 }
367
368 error = if_up(netdev);
369 if (error) {
370 dpctl_error(dpctl_p, error, "%s: failed bringing interface up",
371 name);
372 }
373
374next_destroy_args:
375 netdev_close(netdev);
376 smap_destroy(&args);
377next:
378 free(argcopy);
379 if (error) {
380 lasterror = error;
381 }
382 }
383 dpif_close(dpif);
384
385 return lasterror;
386}
387
388static int
389dpctl_set_if(int argc, const char *argv[], struct dpctl_params *dpctl_p)
390{
391 struct dpif *dpif;
392 int i, error, lasterror = 0;
393
394 error = parsed_dpif_open(argv[1], false, &dpif);
395 if (error) {
396 dpctl_error(dpctl_p, error, "opening datapath");
397 return error;
398 }
399 for (i = 2; i < argc; i++) {
400 struct netdev *netdev = NULL;
401 struct dpif_port dpif_port;
402 char *save_ptr = NULL;
403 char *type = NULL;
404 char *argcopy;
405 const char *name;
406 struct smap args;
407 odp_port_t port_no;
408 char *option;
71f21279
BP
409
410 error = 0;
fceef209
DDP
411
412 argcopy = xstrdup(argv[i]);
413 name = strtok_r(argcopy, ",", &save_ptr);
414 if (!name) {
415 dpctl_error(dpctl_p, 0, "%s is not a valid network device name",
416 argv[i]);
417 goto next;
418 }
419
420 /* Get the port's type from the datapath. */
421 error = dpif_port_query_by_name(dpif, name, &dpif_port);
422 if (error) {
423 dpctl_error(dpctl_p, error, "%s: failed to query port in %s", name,
424 argv[1]);
425 goto next;
426 }
427 type = xstrdup(dpif_port.type);
428 port_no = dpif_port.port_no;
429 dpif_port_destroy(&dpif_port);
430
431 /* Retrieve its existing configuration. */
432 error = netdev_open(name, type, &netdev);
433 if (error) {
434 dpctl_error(dpctl_p, error, "%s: failed to open network device",
435 name);
436 goto next;
437 }
438
439 smap_init(&args);
440 error = netdev_get_config(netdev, &args);
441 if (error) {
442 dpctl_error(dpctl_p, error, "%s: failed to fetch configuration",
443 name);
444 goto next_destroy_args;
445 }
446
447 /* Parse changes to configuration. */
448 while ((option = strtok_r(NULL, ",", &save_ptr)) != NULL) {
449 char *save_ptr_2 = NULL;
450 char *key, *value;
451
452 key = strtok_r(option, "=", &save_ptr_2);
453 value = strtok_r(NULL, "", &save_ptr_2);
454 if (!value) {
455 value = "";
456 }
457
458 if (!strcmp(key, "type")) {
459 if (strcmp(value, type)) {
460 dpctl_error(dpctl_p, 0,
461 "%s: can't change type from %s to %s",
462 name, type, value);
463 error = EINVAL;
79ae214d 464 goto next_destroy_args;
fceef209
DDP
465 }
466 } else if (!strcmp(key, "port_no")) {
467 if (port_no != u32_to_odp(atoi(value))) {
468 dpctl_error(dpctl_p, 0, "%s: can't change port number from"
469 " %"PRIu32" to %d", name, port_no, atoi(value));
470 error = EINVAL;
79ae214d 471 goto next_destroy_args;
fceef209
DDP
472 }
473 } else if (value[0] == '\0') {
474 smap_remove(&args, key);
475 } else {
476 smap_replace(&args, key, value);
477 }
478 }
479
480 /* Update configuration. */
79ae214d
BP
481 char *err_s = NULL;
482 error = netdev_set_config(netdev, &args, &err_s);
483 if (err_s || error) {
7521b9e5 484 dpctl_error(dpctl_p, error, "%s",
79ae214d
BP
485 err_s ? err_s : "Error updating configuration");
486 free(err_s);
487 }
fceef209
DDP
488 if (error) {
489 goto next_destroy_args;
490 }
491
492next_destroy_args:
493 smap_destroy(&args);
494next:
495 netdev_close(netdev);
496 free(type);
497 free(argcopy);
498 if (error) {
499 lasterror = error;
500 }
501 }
502 dpif_close(dpif);
503
504 return lasterror;
505}
506
507static bool
508get_port_number(struct dpif *dpif, const char *name, odp_port_t *port,
509 struct dpctl_params *dpctl_p)
510{
511 struct dpif_port dpif_port;
512
513 if (!dpif_port_query_by_name(dpif, name, &dpif_port)) {
514 *port = dpif_port.port_no;
515 dpif_port_destroy(&dpif_port);
516 return true;
517 } else {
518 dpctl_error(dpctl_p, 0, "no port named %s", name);
519 return false;
520 }
521}
522
523static int
524dpctl_del_if(int argc, const char *argv[], struct dpctl_params *dpctl_p)
525{
526 struct dpif *dpif;
527 int i, error, lasterror = 0;
528
529 error = parsed_dpif_open(argv[1], false, &dpif);
530 if (error) {
531 dpctl_error(dpctl_p, error, "opening datapath");
532 return error;
533 }
534 for (i = 2; i < argc; i++) {
535 const char *name = argv[i];
536 odp_port_t port;
537
538 if (!name[strspn(name, "0123456789")]) {
539 port = u32_to_odp(atoi(name));
540 } else if (!get_port_number(dpif, name, &port, dpctl_p)) {
541 lasterror = ENOENT;
542 continue;
543 }
544
97459c2f 545 error = dpif_port_del(dpif, port, false);
fceef209
DDP
546 if (error) {
547 dpctl_error(dpctl_p, error, "deleting port %s from %s failed",
548 name, argv[1]);
549 lasterror = error;
550 }
551 }
552 dpif_close(dpif);
553 return lasterror;
554}
555
556static void
557print_stat(struct dpctl_params *dpctl_p, const char *leader, uint64_t value)
558{
559 dpctl_print(dpctl_p, "%s", leader);
560 if (value != UINT64_MAX) {
561 dpctl_print(dpctl_p, "%"PRIu64, value);
562 } else {
563 dpctl_print(dpctl_p, "?");
564 }
565}
566
567static void
568print_human_size(struct dpctl_params *dpctl_p, uint64_t value)
569{
570 if (value == UINT64_MAX) {
571 /* Nothing to do. */
572 } else if (value >= 1024ULL * 1024 * 1024 * 1024) {
573 dpctl_print(dpctl_p, " (%.1f TiB)",
574 value / (1024.0 * 1024 * 1024 * 1024));
575 } else if (value >= 1024ULL * 1024 * 1024) {
576 dpctl_print(dpctl_p, " (%.1f GiB)", value / (1024.0 * 1024 * 1024));
577 } else if (value >= 1024ULL * 1024) {
578 dpctl_print(dpctl_p, " (%.1f MiB)", value / (1024.0 * 1024));
579 } else if (value >= 1024) {
580 dpctl_print(dpctl_p, " (%.1f KiB)", value / 1024.0);
581 }
582}
583
3ff1613e
JP
584/* qsort comparison function. */
585static int
586compare_port_nos(const void *a_, const void *b_)
587{
588 const odp_port_t *ap = a_;
589 const odp_port_t *bp = b_;
590 uint32_t a = odp_to_u32(*ap);
591 uint32_t b = odp_to_u32(*bp);
592
593 return a < b ? -1 : a > b;
594}
595
fceef209
DDP
596static void
597show_dpif(struct dpif *dpif, struct dpctl_params *dpctl_p)
598{
599 struct dpif_port_dump dump;
600 struct dpif_port dpif_port;
601 struct dpif_dp_stats stats;
602 struct netdev *netdev;
603
604 dpctl_print(dpctl_p, "%s:\n", dpif_name(dpif));
605 if (!dpif_get_dp_stats(dpif, &stats)) {
d14a36f4
BP
606 dpctl_print(dpctl_p, " lookups: hit:%"PRIu64" missed:%"PRIu64
607 " lost:%"PRIu64"\n flows: %"PRIu64"\n",
fceef209
DDP
608 stats.n_hit, stats.n_missed, stats.n_lost, stats.n_flows);
609 if (stats.n_masks != UINT32_MAX) {
610 uint64_t n_pkts = stats.n_hit + stats.n_missed;
611 double avg = n_pkts ? (double) stats.n_mask_hit / n_pkts : 0.0;
612
d14a36f4 613 dpctl_print(dpctl_p, " masks: hit:%"PRIu64" total:%"PRIu32
fceef209
DDP
614 " hit/pkt:%.2f\n",
615 stats.n_mask_hit, stats.n_masks, avg);
616 }
617 }
618
3ff1613e
JP
619 odp_port_t *port_nos = NULL;
620 size_t allocated_port_nos = 0, n_port_nos = 0;
fceef209 621 DPIF_PORT_FOR_EACH (&dpif_port, &dump, dpif) {
3ff1613e
JP
622 if (n_port_nos >= allocated_port_nos) {
623 port_nos = x2nrealloc(port_nos, &allocated_port_nos,
624 sizeof *port_nos);
625 }
626
627 port_nos[n_port_nos] = dpif_port.port_no;
628 n_port_nos++;
629 }
630
f77ceea3
BB
631 if (port_nos) {
632 qsort(port_nos, n_port_nos, sizeof *port_nos, compare_port_nos);
633 }
3ff1613e
JP
634
635 for (int i = 0; i < n_port_nos; i++) {
636 if (dpif_port_query_by_number(dpif, port_nos[i], &dpif_port)) {
637 continue;
638 }
639
d14a36f4 640 dpctl_print(dpctl_p, " port %u: %s",
fceef209
DDP
641 dpif_port.port_no, dpif_port.name);
642
643 if (strcmp(dpif_port.type, "system")) {
644 int error;
645
646 dpctl_print(dpctl_p, " (%s", dpif_port.type);
647
648 error = netdev_open(dpif_port.name, dpif_port.type, &netdev);
649 if (!error) {
650 struct smap config;
651
652 smap_init(&config);
653 error = netdev_get_config(netdev, &config);
654 if (!error) {
270fa6da
JP
655 const struct smap_node **nodes = smap_sort(&config);
656 for (size_t j = 0; j < smap_count(&config); j++) {
657 const struct smap_node *node = nodes[j];
658 dpctl_print(dpctl_p, "%c %s=%s", j ? ',' : ':',
fceef209
DDP
659 node->key, node->value);
660 }
661 free(nodes);
662 } else {
663 dpctl_print(dpctl_p, ", could not retrieve configuration "
664 "(%s)", ovs_strerror(error));
665 }
666 smap_destroy(&config);
667
668 netdev_close(netdev);
669 } else {
670 dpctl_print(dpctl_p, ": open failed (%s)",
671 ovs_strerror(error));
672 }
673 dpctl_print(dpctl_p, ")");
674 }
675 dpctl_print(dpctl_p, "\n");
676
677 if (dpctl_p->print_statistics) {
678 struct netdev_stats s;
679 int error;
680
681 error = netdev_open(dpif_port.name, dpif_port.type, &netdev);
682 if (error) {
683 dpctl_print(dpctl_p, ", open failed (%s)",
684 ovs_strerror(error));
3ff1613e 685 dpif_port_destroy(&dpif_port);
fceef209
DDP
686 continue;
687 }
688 error = netdev_get_stats(netdev, &s);
689 if (!error) {
690 netdev_close(netdev);
d14a36f4 691 print_stat(dpctl_p, " RX packets:", s.rx_packets);
fceef209
DDP
692 print_stat(dpctl_p, " errors:", s.rx_errors);
693 print_stat(dpctl_p, " dropped:", s.rx_dropped);
694 print_stat(dpctl_p, " overruns:", s.rx_over_errors);
695 print_stat(dpctl_p, " frame:", s.rx_frame_errors);
696 dpctl_print(dpctl_p, "\n");
697
d14a36f4 698 print_stat(dpctl_p, " TX packets:", s.tx_packets);
fceef209
DDP
699 print_stat(dpctl_p, " errors:", s.tx_errors);
700 print_stat(dpctl_p, " dropped:", s.tx_dropped);
701 print_stat(dpctl_p, " aborted:", s.tx_aborted_errors);
702 print_stat(dpctl_p, " carrier:", s.tx_carrier_errors);
703 dpctl_print(dpctl_p, "\n");
704
d14a36f4 705 print_stat(dpctl_p, " collisions:", s.collisions);
fceef209
DDP
706 dpctl_print(dpctl_p, "\n");
707
d14a36f4 708 print_stat(dpctl_p, " RX bytes:", s.rx_bytes);
fceef209
DDP
709 print_human_size(dpctl_p, s.rx_bytes);
710 print_stat(dpctl_p, " TX bytes:", s.tx_bytes);
711 print_human_size(dpctl_p, s.tx_bytes);
712 dpctl_print(dpctl_p, "\n");
713 } else {
714 dpctl_print(dpctl_p, ", could not retrieve stats (%s)",
715 ovs_strerror(error));
716 }
717 }
3ff1613e 718 dpif_port_destroy(&dpif_port);
fceef209 719 }
3ff1613e
JP
720
721 free(port_nos);
1f70f3f0
DDP
722}
723
724typedef void (*dps_for_each_cb)(struct dpif *, struct dpctl_params *);
725
726static int
727dps_for_each(struct dpctl_params *dpctl_p, dps_for_each_cb cb)
728{
729 struct sset dpif_names = SSET_INITIALIZER(&dpif_names),
730 dpif_types = SSET_INITIALIZER(&dpif_types);
88c98bf5 731 int error, openerror = 0, enumerror = 0;
1f70f3f0 732 const char *type, *name;
88c98bf5 733 bool at_least_one = false;
1f70f3f0
DDP
734
735 dp_enumerate_types(&dpif_types);
736
737 SSET_FOR_EACH (type, &dpif_types) {
738 error = dp_enumerate_names(type, &dpif_names);
739 if (error) {
88c98bf5 740 enumerror = error;
1f70f3f0
DDP
741 }
742
743 SSET_FOR_EACH (name, &dpif_names) {
744 struct dpif *dpif;
745
88c98bf5 746 at_least_one = true;
1f70f3f0
DDP
747 error = dpif_open(name, type, &dpif);
748 if (!error) {
749 cb(dpif, dpctl_p);
750 dpif_close(dpif);
751 } else {
88c98bf5 752 openerror = error;
1f70f3f0
DDP
753 dpctl_error(dpctl_p, error, "opening datapath %s failed",
754 name);
755 }
756 }
757 }
758
759 sset_destroy(&dpif_names);
760 sset_destroy(&dpif_types);
761
88c98bf5
DDP
762 /* If there has been an error while opening a datapath it should be
763 * reported. Otherwise, we want to ignore the errors generated by
764 * dp_enumerate_names() if at least one datapath has been discovered,
765 * because they're not interesting for the user. This happens, for
766 * example, if OVS is using a userspace datapath and the kernel module
767 * is not loaded. */
768 if (openerror) {
769 return openerror;
770 } else {
771 return at_least_one ? 0 : enumerror;
772 }
fceef209
DDP
773}
774
775static int
776dpctl_show(int argc, const char *argv[], struct dpctl_params *dpctl_p)
777{
778 int error, lasterror = 0;
779 if (argc > 1) {
780 int i;
781 for (i = 1; i < argc; i++) {
782 const char *name = argv[i];
783 struct dpif *dpif;
784
785 error = parsed_dpif_open(name, false, &dpif);
786 if (!error) {
787 show_dpif(dpif, dpctl_p);
1f70f3f0 788 dpif_close(dpif);
fceef209
DDP
789 } else {
790 dpctl_error(dpctl_p, error, "opening datapath %s failed",
791 name);
792 lasterror = error;
793 }
794 }
795 } else {
1f70f3f0 796 lasterror = dps_for_each(dpctl_p, show_dpif);
fceef209 797 }
1f70f3f0 798
fceef209
DDP
799 return lasterror;
800}
801
1f70f3f0
DDP
802static void
803dump_cb(struct dpif *dpif, struct dpctl_params *dpctl_p)
804{
805 dpctl_print(dpctl_p, "%s\n", dpif_name(dpif));
806}
807
fceef209
DDP
808static int
809dpctl_dump_dps(int argc OVS_UNUSED, const char *argv[] OVS_UNUSED,
810 struct dpctl_params *dpctl_p)
811{
1f70f3f0 812 return dps_for_each(dpctl_p, dump_cb);
fceef209
DDP
813}
814
818650e6
JS
815static void
816format_dpif_flow(struct ds *ds, const struct dpif_flow *f, struct hmap *ports,
d63ca532 817 struct dpctl_params *dpctl_p)
818650e6 818{
fbe794aa
JS
819 if (dpctl_p->verbosity && f->ufid_present) {
820 odp_format_ufid(&f->ufid, ds);
821 ds_put_cstr(ds, ", ");
818650e6
JS
822 }
823 odp_flow_format(f->key, f->key_len, f->mask, f->mask_len, ports, ds,
824 dpctl_p->verbosity);
825 ds_put_cstr(ds, ", ");
826
827 dpif_flow_stats_format(&f->stats, ds);
d63ca532 828 if (dpctl_p->verbosity && f->attrs.offloaded) {
4742003c
PB
829 ds_put_cstr(ds, ", offloaded:yes");
830 }
d63ca532
GT
831 if (dpctl_p->verbosity && f->attrs.dp_layer) {
832 ds_put_format(ds, ", dp:%s", f->attrs.dp_layer);
833 }
818650e6 834 ds_put_cstr(ds, ", actions:");
0722f341 835 format_odp_actions(ds, f->actions, f->actions_len, ports);
818650e6
JS
836}
837
494a7455
JP
838static char *supported_dump_types[] = {
839 "offloaded",
840 "ovs",
7e8b7199
PB
841};
842
d63ca532 843static bool
494a7455 844flow_passes_type_filter(const struct dpif_flow *f, char *type)
d63ca532 845{
494a7455
JP
846 if (!strcmp(type, "offloaded")) {
847 return f->attrs.offloaded;
d63ca532 848 }
494a7455 849 return true;
d63ca532
GT
850}
851
d1fd1ea9
BP
852static struct hmap *
853dpctl_get_portno_names(struct dpif *dpif, const struct dpctl_params *dpctl_p)
854{
855 if (dpctl_p->names) {
856 struct hmap *portno_names = xmalloc(sizeof *portno_names);
857 hmap_init(portno_names);
858
859 struct dpif_port_dump port_dump;
860 struct dpif_port dpif_port;
861 DPIF_PORT_FOR_EACH (&dpif_port, &port_dump, dpif) {
862 odp_portno_names_set(portno_names, dpif_port.port_no,
863 dpif_port.name);
864 }
865
866 return portno_names;
867 } else {
868 return NULL;
869 }
870}
871
872static void
873dpctl_free_portno_names(struct hmap *portno_names)
874{
875 if (portno_names) {
876 odp_portno_names_destroy(portno_names);
877 hmap_destroy(portno_names);
878 free(portno_names);
879 }
880}
881
fceef209
DDP
882static int
883dpctl_dump_flows(int argc, const char *argv[], struct dpctl_params *dpctl_p)
884{
885 struct dpif *dpif;
886 struct ds ds;
fceef209
DDP
887
888 char *filter = NULL;
494a7455 889 char *type = NULL;
fceef209
DDP
890 struct flow flow_filter;
891 struct flow_wildcards wc_filter;
892
fceef209
DDP
893 struct dpif_flow_dump_thread *flow_dump_thread;
894 struct dpif_flow_dump *flow_dump;
895 struct dpif_flow f;
1c1e46ed 896 int pmd_id = PMD_ID_NULL;
7e8b7199 897 int lastargc = 0;
fceef209
DDP
898 int error;
899
7e8b7199
PB
900 while (argc > 1 && lastargc != argc) {
901 lastargc = argc;
902 if (!strncmp(argv[argc - 1], "filter=", 7) && !filter) {
903 filter = xstrdup(argv[--argc] + 7);
494a7455
JP
904 } else if (!strncmp(argv[argc - 1], "type=", 5) && !type) {
905 type = xstrdup(argv[--argc] + 5);
7e8b7199 906 }
fceef209 907 }
7e8b7199 908
7cfb862c 909 error = opt_dpif_open(argc, argv, dpctl_p, 2, &dpif, NULL);
fceef209 910 if (error) {
7e8b7199 911 goto out_free;
fceef209
DDP
912 }
913
d1fd1ea9 914 struct hmap *portno_names = dpctl_get_portno_names(dpif, dpctl_p);
fceef209
DDP
915
916 if (filter) {
50f96b10
BP
917 struct ofputil_port_map port_map;
918 ofputil_port_map_init(&port_map);
d1fd1ea9
BP
919
920 struct dpif_port_dump port_dump;
921 struct dpif_port dpif_port;
50f96b10
BP
922 DPIF_PORT_FOR_EACH (&dpif_port, &port_dump, dpif) {
923 ofputil_port_map_put(&port_map,
924 u16_to_ofp(odp_to_u32(dpif_port.port_no)),
925 dpif_port.name);
926 }
927 char *err = parse_ofp_exact_flow(&flow_filter, &wc_filter, NULL,
928 filter, &port_map);
929 ofputil_port_map_destroy(&port_map);
fceef209
DDP
930 if (err) {
931 dpctl_error(dpctl_p, 0, "Failed to parse filter (%s)", err);
a129fe8c 932 free(err);
fceef209
DDP
933 error = EINVAL;
934 goto out_dpifclose;
935 }
936 }
937
494a7455
JP
938 if (type) {
939 error = EINVAL;
940 for (int i = 0; i < ARRAY_SIZE(supported_dump_types); i++) {
941 if (!strcmp(supported_dump_types[i], type)) {
942 error = 0;
943 break;
944 }
945 }
946 if (error) {
947 dpctl_error(dpctl_p, error, "Failed to parse type (%s)", type);
948 goto out_free;
949 }
7e8b7199
PB
950 }
951
d5c199ea
DDP
952 /* Make sure that these values are different. PMD_ID_NULL means that the
953 * pmd is unspecified (e.g. because the datapath doesn't have different
954 * pmd threads), while NON_PMD_CORE_ID refers to every non pmd threads
955 * in the userspace datapath */
956 BUILD_ASSERT(PMD_ID_NULL != NON_PMD_CORE_ID);
957
fceef209 958 ds_init(&ds);
4742003c 959 memset(&f, 0, sizeof f);
494a7455 960 flow_dump = dpif_flow_dump_create(dpif, false, (type ? type : "dpctl"));
fceef209
DDP
961 flow_dump_thread = dpif_flow_dump_thread_create(flow_dump);
962 while (dpif_flow_dump_next(flow_dump_thread, &f, 1)) {
963 if (filter) {
964 struct flow flow;
965 struct flow_wildcards wc;
966 struct match match, match_filter;
967 struct minimatch minimatch;
968
969 odp_flow_key_to_flow(f.key, f.key_len, &flow);
8d8ab6c2 970 odp_flow_key_to_mask(f.mask, f.mask_len, &wc, &flow);
fceef209
DDP
971 match_init(&match, &flow, &wc);
972
973 match_init(&match_filter, &flow_filter, &wc);
974 match_init(&match_filter, &match_filter.flow, &wc_filter);
975 minimatch_init(&minimatch, &match_filter);
976
977 if (!minimatch_matches_flow(&minimatch, &match.flow)) {
978 minimatch_destroy(&minimatch);
979 continue;
980 }
981 minimatch_destroy(&minimatch);
982 }
983 ds_clear(&ds);
1c1e46ed
AW
984 /* If 'pmd_id' is specified, overlapping flows could be dumped from
985 * different pmd threads. So, separates dumps from different pmds
986 * by printing a title line. */
987 if (pmd_id != f.pmd_id) {
988 if (f.pmd_id == NON_PMD_CORE_ID) {
989 ds_put_format(&ds, "flow-dump from non-dpdk interfaces:\n");
990 } else {
991 ds_put_format(&ds, "flow-dump from pmd on cpu core: %d\n",
992 f.pmd_id);
993 }
994 pmd_id = f.pmd_id;
995 }
494a7455 996 if (!type || flow_passes_type_filter(&f, type)) {
d63ca532
GT
997 format_dpif_flow(&ds, &f, portno_names, dpctl_p);
998 dpctl_print(dpctl_p, "%s\n", ds_cstr(&ds));
999 }
fceef209
DDP
1000 }
1001 dpif_flow_dump_thread_destroy(flow_dump_thread);
1002 error = dpif_flow_dump_destroy(flow_dump);
1003
1004 if (error) {
1005 dpctl_error(dpctl_p, error, "Failed to dump flows from datapath");
1006 }
1007 ds_destroy(&ds);
1008
1009out_dpifclose:
d1fd1ea9 1010 dpctl_free_portno_names(portno_names);
fceef209 1011 dpif_close(dpif);
7e8b7199 1012out_free:
fceef209 1013 free(filter);
494a7455 1014 free(type);
fceef209
DDP
1015 return error;
1016}
1017
1018static int
1019dpctl_put_flow(int argc, const char *argv[], enum dpif_flow_put_flags flags,
1020 struct dpctl_params *dpctl_p)
1021{
1022 const char *key_s = argv[argc - 2];
1023 const char *actions_s = argv[argc - 1];
1024 struct dpif_flow_stats stats;
1025 struct dpif_port dpif_port;
1026 struct dpif_port_dump port_dump;
1027 struct ofpbuf actions;
1028 struct ofpbuf key;
1029 struct ofpbuf mask;
1030 struct dpif *dpif;
534a19b9
JS
1031 ovs_u128 ufid;
1032 bool ufid_present;
fceef209 1033 struct simap port_names;
534a19b9 1034 int n, error;
fceef209 1035
7cfb862c 1036 error = opt_dpif_open(argc, argv, dpctl_p, 4, &dpif, NULL);
fceef209 1037 if (error) {
fceef209
DDP
1038 return error;
1039 }
1040
534a19b9
JS
1041 ufid_present = false;
1042 n = odp_ufid_from_string(key_s, &ufid);
1043 if (n < 0) {
1044 dpctl_error(dpctl_p, -n, "parsing flow ufid");
1045 return -n;
1046 } else if (n) {
1047 key_s += n;
1048 ufid_present = true;
1049 }
fceef209
DDP
1050
1051 simap_init(&port_names);
1052 DPIF_PORT_FOR_EACH (&dpif_port, &port_dump, dpif) {
1053 simap_put(&port_names, dpif_port.name, odp_to_u32(dpif_port.port_no));
1054 }
1055
1056 ofpbuf_init(&key, 0);
1057 ofpbuf_init(&mask, 0);
1058 error = odp_flow_from_string(key_s, &port_names, &key, &mask);
1059 simap_destroy(&port_names);
1060 if (error) {
1061 dpctl_error(dpctl_p, error, "parsing flow key");
1062 goto out_freekeymask;
1063 }
1064
1065 ofpbuf_init(&actions, 0);
1066 error = odp_actions_from_string(actions_s, NULL, &actions);
1067 if (error) {
1068 dpctl_error(dpctl_p, error, "parsing actions");
1069 goto out_freeactions;
1070 }
1c1e46ed 1071
f5d317a1
DDP
1072 /* The flow will be added on all pmds currently in the datapath. */
1073 error = dpif_flow_put(dpif, flags,
1074 key.data, key.size,
1075 mask.size == 0 ? NULL : mask.data,
1076 mask.size, actions.data,
1077 actions.size, ufid_present ? &ufid : NULL,
1078 PMD_ID_NULL,
1079 dpctl_p->print_statistics ? &stats : NULL);
1080
fceef209
DDP
1081 if (error) {
1082 dpctl_error(dpctl_p, error, "updating flow table");
1083 goto out_freeactions;
1084 }
1085
1086 if (dpctl_p->print_statistics) {
1087 struct ds s;
1088
1089 ds_init(&s);
1090 dpif_flow_stats_format(&stats, &s);
1091 dpctl_print(dpctl_p, "%s\n", ds_cstr(&s));
1092 ds_destroy(&s);
1093 }
1094
1095out_freeactions:
1096 ofpbuf_uninit(&actions);
1097out_freekeymask:
1098 ofpbuf_uninit(&mask);
1099 ofpbuf_uninit(&key);
1100 dpif_close(dpif);
1101 return error;
1102}
1103
1104static int
1105dpctl_add_flow(int argc, const char *argv[], struct dpctl_params *dpctl_p)
1106{
1107 return dpctl_put_flow(argc, argv, DPIF_FP_CREATE, dpctl_p);
1108}
1109
1110static int
1111dpctl_mod_flow(int argc, const char *argv[], struct dpctl_params *dpctl_p)
1112{
1113 enum dpif_flow_put_flags flags;
1114
1115 flags = DPIF_FP_MODIFY;
1116 if (dpctl_p->may_create) {
1117 flags |= DPIF_FP_CREATE;
1118 }
1119 if (dpctl_p->zero_statistics) {
1120 flags |= DPIF_FP_ZERO_STATS;
1121 }
1122
1123 return dpctl_put_flow(argc, argv, flags, dpctl_p);
1124}
1125
818650e6
JS
1126static int
1127dpctl_get_flow(int argc, const char *argv[], struct dpctl_params *dpctl_p)
1128{
1129 const char *key_s = argv[argc - 1];
1130 struct dpif_flow flow;
818650e6 1131 struct dpif *dpif;
818650e6
JS
1132 ovs_u128 ufid;
1133 struct ofpbuf buf;
1134 uint64_t stub[DPIF_FLOW_BUFSIZE / 8];
1135 struct ds ds;
1136 int n, error;
1137
7cfb862c 1138 error = opt_dpif_open(argc, argv, dpctl_p, 3, &dpif, NULL);
818650e6 1139 if (error) {
818650e6
JS
1140 return error;
1141 }
1142
1143 ofpbuf_use_stub(&buf, &stub, sizeof stub);
d1fd1ea9
BP
1144
1145 struct hmap *portno_names = dpctl_get_portno_names(dpif, dpctl_p);
818650e6
JS
1146
1147 n = odp_ufid_from_string(key_s, &ufid);
1148 if (n <= 0) {
1149 dpctl_error(dpctl_p, -n, "parsing flow ufid");
1150 goto out;
1151 }
1152
c673049c 1153 /* In case of PMD will be returned flow from first PMD thread with match. */
1c1e46ed 1154 error = dpif_flow_get(dpif, NULL, 0, &ufid, PMD_ID_NULL, &buf, &flow);
818650e6
JS
1155 if (error) {
1156 dpctl_error(dpctl_p, error, "getting flow");
1157 goto out;
1158 }
1159
1160 ds_init(&ds);
d63ca532 1161 format_dpif_flow(&ds, &flow, portno_names, dpctl_p);
818650e6
JS
1162 dpctl_print(dpctl_p, "%s\n", ds_cstr(&ds));
1163 ds_destroy(&ds);
1164
1165out:
d1fd1ea9 1166 dpctl_free_portno_names(portno_names);
818650e6
JS
1167 ofpbuf_uninit(&buf);
1168 dpif_close(dpif);
1169 return error;
1170}
1171
fceef209
DDP
1172static int
1173dpctl_del_flow(int argc, const char *argv[], struct dpctl_params *dpctl_p)
1174{
1175 const char *key_s = argv[argc - 1];
1176 struct dpif_flow_stats stats;
1177 struct dpif_port dpif_port;
1178 struct dpif_port_dump port_dump;
1179 struct ofpbuf key;
1180 struct ofpbuf mask; /* To be ignored. */
1181 struct dpif *dpif;
534a19b9
JS
1182 ovs_u128 ufid;
1183 bool ufid_present;
fceef209 1184 struct simap port_names;
534a19b9 1185 int n, error;
fceef209 1186
7cfb862c 1187 error = opt_dpif_open(argc, argv, dpctl_p, 3, &dpif, NULL);
fceef209 1188 if (error) {
fceef209
DDP
1189 return error;
1190 }
1191
534a19b9
JS
1192 ufid_present = false;
1193 n = odp_ufid_from_string(key_s, &ufid);
1194 if (n < 0) {
1195 dpctl_error(dpctl_p, -n, "parsing flow ufid");
1196 return -n;
1197 } else if (n) {
1198 key_s += n;
1199 ufid_present = true;
1200 }
1201
fceef209
DDP
1202 simap_init(&port_names);
1203 DPIF_PORT_FOR_EACH (&dpif_port, &port_dump, dpif) {
1204 simap_put(&port_names, dpif_port.name, odp_to_u32(dpif_port.port_no));
1205 }
1206
1207 ofpbuf_init(&key, 0);
1208 ofpbuf_init(&mask, 0);
1209
1210 error = odp_flow_from_string(key_s, &port_names, &key, &mask);
1211 if (error) {
1212 dpctl_error(dpctl_p, error, "parsing flow key");
1213 goto out;
1214 }
1215
f5d317a1
DDP
1216 /* The flow will be deleted from all pmds currently in the datapath. */
1217 error = dpif_flow_del(dpif, key.data, key.size,
1218 ufid_present ? &ufid : NULL, PMD_ID_NULL,
1219 dpctl_p->print_statistics ? &stats : NULL);
1220
fceef209
DDP
1221 if (error) {
1222 dpctl_error(dpctl_p, error, "deleting flow");
534a19b9
JS
1223 if (error == ENOENT && !ufid_present) {
1224 struct ds s;
1225
1226 ds_init(&s);
1227 ds_put_format(&s, "Perhaps you need to specify a UFID?");
1228 dpctl_print(dpctl_p, "%s\n", ds_cstr(&s));
1229 ds_destroy(&s);
1230 }
fceef209
DDP
1231 goto out;
1232 }
1233
1234 if (dpctl_p->print_statistics) {
1235 struct ds s;
1236
1237 ds_init(&s);
1238 dpif_flow_stats_format(&stats, &s);
1239 dpctl_print(dpctl_p, "%s\n", ds_cstr(&s));
1240 ds_destroy(&s);
1241 }
1242
1243out:
1244 ofpbuf_uninit(&mask);
1245 ofpbuf_uninit(&key);
1246 simap_destroy(&port_names);
1247 dpif_close(dpif);
1248 return error;
1249}
1250
1251static int
1252dpctl_del_flows(int argc, const char *argv[], struct dpctl_params *dpctl_p)
1253{
1254 struct dpif *dpif;
fceef209 1255
7cfb862c 1256 int error = opt_dpif_open(argc, argv, dpctl_p, 2, &dpif, NULL);
fceef209 1257 if (error) {
fceef209
DDP
1258 return error;
1259 }
1260
1261 error = dpif_flow_flush(dpif);
1262 if (error) {
1263 dpctl_error(dpctl_p, error, "deleting all flows");
1264 }
1265 dpif_close(dpif);
1266 return error;
1267}
1268
1269static int
1270dpctl_help(int argc OVS_UNUSED, const char *argv[] OVS_UNUSED,
1271 struct dpctl_params *dpctl_p)
1272{
1273 if (dpctl_p->usage) {
1274 dpctl_p->usage(dpctl_p->aux);
1275 }
56cad666
AW
1276
1277 return 0;
1278}
1279
1280static int
1281dpctl_list_commands(int argc OVS_UNUSED, const char *argv[] OVS_UNUSED,
1282 struct dpctl_params *dpctl_p)
1283{
1284 struct ds ds = DS_EMPTY_INITIALIZER;
1285 const struct dpctl_command *commands = get_all_dpctl_commands();
1286
1287 ds_put_cstr(&ds, "The available commands are:\n");
1288 for (; commands->name; commands++) {
1289 const struct dpctl_command *c = commands;
1290
1291 ds_put_format(&ds, " %s%-23s %s\n", dpctl_p->is_appctl ? "dpctl/" : "",
1292 c->name, c->usage);
1293 }
1294 dpctl_puts(dpctl_p, false, ds.string);
1295 ds_destroy(&ds);
1296
fceef209
DDP
1297 return 0;
1298}
f33cdd7b 1299\f
dffae65f
DDP
1300
1301static int
1302dpctl_dump_conntrack(int argc, const char *argv[],
1303 struct dpctl_params *dpctl_p)
1304{
1305 struct ct_dpif_dump_state *dump;
1306 struct ct_dpif_entry cte;
1307 uint16_t zone, *pzone = NULL;
ded30c74 1308 int tot_bkts;
dffae65f 1309 struct dpif *dpif;
dffae65f
DDP
1310 int error;
1311
1312 if (argc > 1 && ovs_scan(argv[argc - 1], "zone=%"SCNu16, &zone)) {
1313 pzone = &zone;
1314 argc--;
1315 }
f33cdd7b 1316
7cfb862c 1317 error = opt_dpif_open(argc, argv, dpctl_p, 2, &dpif, NULL);
dffae65f 1318 if (error) {
dffae65f
DDP
1319 return error;
1320 }
1321
ded30c74 1322 error = ct_dpif_dump_start(dpif, &dump, pzone, &tot_bkts);
dffae65f
DDP
1323 if (error) {
1324 dpctl_error(dpctl_p, error, "starting conntrack dump");
1325 dpif_close(dpif);
1326 return error;
1327 }
1328
97ee6d41 1329 while (!(error = ct_dpif_dump_next(dump, &cte))) {
dffae65f
DDP
1330 struct ds s = DS_EMPTY_INITIALIZER;
1331
1332 ct_dpif_format_entry(&cte, &s, dpctl_p->verbosity,
1333 dpctl_p->print_statistics);
1334 ct_dpif_entry_uninit(&cte);
1335
1336 dpctl_print(dpctl_p, "%s\n", ds_cstr(&s));
1337 ds_destroy(&s);
1338 }
97ee6d41
FA
1339 if (error == EOF) {
1340 /* Any CT entry was dumped with no issue. */
1341 error = 0;
1342 } else if (error) {
1343 dpctl_error(dpctl_p, error, "dumping conntrack entry");
1344 }
1345
dffae65f
DDP
1346 ct_dpif_dump_done(dump);
1347 dpif_close(dpif);
1348 return error;
1349}
1350
7f278d1f
DDP
1351static int
1352dpctl_flush_conntrack(int argc, const char *argv[],
1353 struct dpctl_params *dpctl_p)
1354{
2f15f8f3 1355 struct dpif *dpif = NULL;
c43a1331
YHW
1356 struct ct_dpif_tuple tuple, *ptuple = NULL;
1357 struct ds ds = DS_EMPTY_INITIALIZER;
7f278d1f 1358 uint16_t zone, *pzone = NULL;
2f15f8f3
DB
1359 int error;
1360 int args = argc - 1;
1361
1362 /* Parse ct tuple */
1363 if (args && ct_dpif_parse_tuple(&tuple, argv[args], &ds)) {
1364 ptuple = &tuple;
1365 args--;
c43a1331 1366 }
7f278d1f 1367
c43a1331 1368 /* Parse zone */
2f15f8f3 1369 if (args && ovs_scan(argv[args], "zone=%"SCNu16, &zone)) {
7f278d1f 1370 pzone = &zone;
2f15f8f3 1371 args--;
7f278d1f 1372 }
2f15f8f3 1373
c43a1331 1374 /* Report error if there are more than one unparsed argument. */
2f15f8f3
DB
1375 if (args > 1) {
1376 ds_put_cstr(&ds, "invalid arguments");
c43a1331
YHW
1377 error = EINVAL;
1378 goto error;
7f278d1f 1379 }
c43a1331 1380
7cfb862c 1381 error = opt_dpif_open(argc, argv, dpctl_p, 4, &dpif, NULL);
2f15f8f3
DB
1382 if (error) {
1383 return error;
7f278d1f
DDP
1384 }
1385
c43a1331
YHW
1386 error = ct_dpif_flush(dpif, pzone, ptuple);
1387 if (!error) {
1388 dpif_close(dpif);
1389 return 0;
1390 } else {
1391 ds_put_cstr(&ds, "failed to flush conntrack");
1392 }
7f278d1f 1393
c43a1331
YHW
1394error:
1395 dpctl_error(dpctl_p, error, "%s", ds_cstr(&ds));
1396 ds_destroy(&ds);
7f278d1f
DDP
1397 dpif_close(dpif);
1398 return error;
1399}
8a0d9d85
FA
1400
1401static int
1402dpctl_ct_stats_show(int argc, const char *argv[],
1403 struct dpctl_params *dpctl_p)
1404{
1405 struct dpif *dpif;
8a0d9d85
FA
1406 struct ct_dpif_dump_state *dump;
1407 struct ct_dpif_entry cte;
1408 uint16_t zone, *pzone = NULL;
ded30c74 1409 int tot_bkts;
8a0d9d85
FA
1410 int lastargc = 0;
1411
1412 int proto_stats[CT_STATS_MAX];
1413 int tcp_conn_per_states[CT_DPIF_TCPS_MAX_NUM];
1414 int error;
1415
16b361ef
JP
1416 bool verbose = dpctl_p->verbosity;
1417
8a0d9d85
FA
1418 while (argc > 1 && lastargc != argc) {
1419 lastargc = argc;
1420 if (!strncmp(argv[argc - 1], "verbose", 7)) {
16b361ef 1421 /* Support "verbose" argument for backwards compatibility. */
8a0d9d85
FA
1422 verbose = true;
1423 argc--;
1424 } else if (!strncmp(argv[argc - 1], "zone=", 5)) {
1425 if (ovs_scan(argv[argc - 1], "zone=%"SCNu16, &zone)) {
1426 pzone = &zone;
1427 argc--;
1428 }
1429 }
1430 }
8a0d9d85 1431
7cfb862c 1432 error = opt_dpif_open(argc, argv, dpctl_p, 2, &dpif, NULL);
8a0d9d85 1433 if (error) {
8a0d9d85
FA
1434 return error;
1435 }
1436
1437 memset(proto_stats, 0, sizeof(proto_stats));
1438 memset(tcp_conn_per_states, 0, sizeof(tcp_conn_per_states));
ded30c74 1439 error = ct_dpif_dump_start(dpif, &dump, pzone, &tot_bkts);
8a0d9d85
FA
1440 if (error) {
1441 dpctl_error(dpctl_p, error, "starting conntrack dump");
1442 dpif_close(dpif);
1443 return error;
1444 }
1445
1446 int tot_conn = 0;
97ee6d41 1447 while (!(error = ct_dpif_dump_next(dump, &cte))) {
8a0d9d85
FA
1448 ct_dpif_entry_uninit(&cte);
1449 tot_conn++;
1450 switch (cte.tuple_orig.ip_proto) {
1451 case IPPROTO_ICMP:
1452 proto_stats[CT_STATS_ICMP]++;
1453 break;
1454 case IPPROTO_ICMPV6:
1455 proto_stats[CT_STATS_ICMPV6]++;
1456 break;
1457 case IPPROTO_TCP:
1458 proto_stats[CT_STATS_TCP]++;
1459 uint8_t tcp_state;
1460 /* We keep two separate tcp states, but we print just one. The
1461 * Linux kernel connection tracker internally keeps only one state,
1462 * so 'state_orig' and 'state_reply', will be the same. */
1463 tcp_state = MAX(cte.protoinfo.tcp.state_orig,
1464 cte.protoinfo.tcp.state_reply);
1465 tcp_state = ct_dpif_coalesce_tcp_state(tcp_state);
1466 tcp_conn_per_states[tcp_state]++;
1467 break;
1468 case IPPROTO_UDP:
1469 proto_stats[CT_STATS_UDP]++;
1470 break;
1471 case IPPROTO_SCTP:
1472 proto_stats[CT_STATS_SCTP]++;
1473 break;
1474 case IPPROTO_UDPLITE:
1475 proto_stats[CT_STATS_UDPLITE]++;
1476 break;
1477 case IPPROTO_DCCP:
1478 proto_stats[CT_STATS_DCCP]++;
1479 break;
1480 case IPPROTO_IGMP:
1481 proto_stats[CT_STATS_IGMP]++;
1482 break;
1483 default:
1484 proto_stats[CT_STATS_OTHER]++;
1485 break;
1486 }
1487 }
97ee6d41
FA
1488 if (error == EOF) {
1489 /* All CT entries were dumped with no issue. */
1490 error = 0;
1491 } else if (error) {
1492 dpctl_error(dpctl_p, error, "dumping conntrack entry");
1493 /* Fall through to show any other info we collected. */
1494 }
8a0d9d85
FA
1495
1496 dpctl_print(dpctl_p, "Connections Stats:\n Total: %d\n", tot_conn);
1497 if (proto_stats[CT_STATS_TCP]) {
d14a36f4 1498 dpctl_print(dpctl_p, " TCP: %d\n", proto_stats[CT_STATS_TCP]);
8a0d9d85 1499 if (verbose) {
d14a36f4 1500 dpctl_print(dpctl_p, " Conn per TCP states:\n");
8a0d9d85
FA
1501 for (int i = 0; i < CT_DPIF_TCPS_MAX_NUM; i++) {
1502 if (tcp_conn_per_states[i]) {
1503 struct ds s = DS_EMPTY_INITIALIZER;
1504 ct_dpif_format_tcp_stat(&s, i, tcp_conn_per_states[i]);
1505 dpctl_print(dpctl_p, "%s\n", ds_cstr(&s));
1506 ds_destroy(&s);
1507 }
1508 }
1509 }
1510 }
1511 if (proto_stats[CT_STATS_UDP]) {
d14a36f4 1512 dpctl_print(dpctl_p, " UDP: %d\n", proto_stats[CT_STATS_UDP]);
8a0d9d85
FA
1513 }
1514 if (proto_stats[CT_STATS_UDPLITE]) {
d14a36f4 1515 dpctl_print(dpctl_p, " UDPLITE: %d\n", proto_stats[CT_STATS_UDPLITE]);
8a0d9d85
FA
1516 }
1517 if (proto_stats[CT_STATS_SCTP]) {
d14a36f4 1518 dpctl_print(dpctl_p, " SCTP: %d\n", proto_stats[CT_STATS_SCTP]);
8a0d9d85
FA
1519 }
1520 if (proto_stats[CT_STATS_ICMP]) {
d14a36f4 1521 dpctl_print(dpctl_p, " ICMP: %d\n", proto_stats[CT_STATS_ICMP]);
8a0d9d85
FA
1522 }
1523 if (proto_stats[CT_STATS_DCCP]) {
d14a36f4 1524 dpctl_print(dpctl_p, " DCCP: %d\n", proto_stats[CT_STATS_DCCP]);
8a0d9d85
FA
1525 }
1526 if (proto_stats[CT_STATS_IGMP]) {
d14a36f4 1527 dpctl_print(dpctl_p, " IGMP: %d\n", proto_stats[CT_STATS_IGMP]);
8a0d9d85
FA
1528 }
1529 if (proto_stats[CT_STATS_OTHER]) {
d14a36f4 1530 dpctl_print(dpctl_p, " Other: %d\n", proto_stats[CT_STATS_OTHER]);
8a0d9d85
FA
1531 }
1532
1533 ct_dpif_dump_done(dump);
1534 dpif_close(dpif);
1535 return error;
1536}
ded30c74
FA
1537
1538#define CT_BKTS_GT "gt="
1539static int
1540dpctl_ct_bkts(int argc, const char *argv[],
1541 struct dpctl_params *dpctl_p)
1542{
1543 struct dpif *dpif;
ded30c74
FA
1544 struct ct_dpif_dump_state *dump;
1545 struct ct_dpif_entry cte;
1546 uint16_t gt = 0; /* Threshold: display value when greater than gt. */
1547 uint16_t *pzone = NULL;
1548 int tot_bkts = 0;
1549 int error;
1550
1551 if (argc > 1 && !strncmp(argv[argc - 1], CT_BKTS_GT, strlen(CT_BKTS_GT))) {
1552 if (ovs_scan(argv[argc - 1], CT_BKTS_GT"%"SCNu16, &gt)) {
1553 argc--;
1554 }
1555 }
1556
7cfb862c 1557 error = opt_dpif_open(argc, argv, dpctl_p, 2, &dpif, NULL);
ded30c74 1558 if (error) {
ded30c74
FA
1559 return error;
1560 }
1561
1562 error = ct_dpif_dump_start(dpif, &dump, pzone, &tot_bkts);
1563 if (error) {
1564 dpctl_error(dpctl_p, error, "starting conntrack dump");
1565 dpif_close(dpif);
1566 return error;
1567 }
1568 if (tot_bkts == -1) {
1569 /* Command not available when called by kernel OvS. */
1570 dpctl_print(dpctl_p,
1571 "Command is available for UserSpace ConnTracker only.\n");
1572 ct_dpif_dump_done(dump);
1573 dpif_close(dpif);
1574 return 0;
1575 }
1576
1577 dpctl_print(dpctl_p, "Total Buckets: %d\n", tot_bkts);
1578
1579 int tot_conn = 0;
1580 uint32_t *conn_per_bkts = xzalloc(tot_bkts * sizeof(uint32_t));
1581
97ee6d41 1582 while (!(error = ct_dpif_dump_next(dump, &cte))) {
ded30c74
FA
1583 ct_dpif_entry_uninit(&cte);
1584 tot_conn++;
1585 if (tot_bkts > 0) {
1586 if (cte.bkt < tot_bkts) {
1587 conn_per_bkts[cte.bkt]++;
1588 } else {
1589 dpctl_print(dpctl_p, "Bucket nr out of range: %d >= %d\n",
1590 cte.bkt, tot_bkts);
1591 }
1592 }
1593 }
97ee6d41
FA
1594 if (error == EOF) {
1595 /* All CT entries were dumped with no issue. */
1596 error = 0;
1597 } else if (error) {
1598 dpctl_error(dpctl_p, error, "dumping conntrack entry");
1599 /* Fall through and display all the collected info. */
1600 }
ded30c74
FA
1601
1602 dpctl_print(dpctl_p, "Current Connections: %d\n", tot_conn);
1603 dpctl_print(dpctl_p, "\n");
1604 if (tot_bkts && tot_conn) {
1605 dpctl_print(dpctl_p, "+-----------+"
1606 "-----------------------------------------+\n");
1607 dpctl_print(dpctl_p, "| Buckets |"
1608 " Connections per Buckets |\n");
1609 dpctl_print(dpctl_p, "+-----------+"
1610 "-----------------------------------------+");
1611#define NUM_BKTS_DIPLAYED_PER_ROW 8
1612 for (int i = 0; i < tot_bkts; i++) {
1613 if (i % NUM_BKTS_DIPLAYED_PER_ROW == 0) {
1614 dpctl_print(dpctl_p, "\n %3d..%3d | ",
1615 i, i + NUM_BKTS_DIPLAYED_PER_ROW - 1);
1616 }
1617 if (conn_per_bkts[i] > gt) {
1618 dpctl_print(dpctl_p, "%5d", conn_per_bkts[i]);
1619 } else {
1620 dpctl_print(dpctl_p, "%5s", ".");
1621 }
1622 }
1623 dpctl_print(dpctl_p, "\n\n");
1624 }
1625
1626 ct_dpif_dump_done(dump);
1627 dpif_close(dpif);
1628 free(conn_per_bkts);
1629 return error;
1630}
fceef209 1631\f
c92339ad
DB
1632static int
1633dpctl_ct_set_maxconns(int argc, const char *argv[],
1634 struct dpctl_params *dpctl_p)
1635{
1636 struct dpif *dpif;
7cfb862c 1637 int error = opt_dpif_open(argc, argv, dpctl_p, 3, &dpif, NULL);
c92339ad
DB
1638 if (!error) {
1639 uint32_t maxconns;
1640 if (ovs_scan(argv[argc - 1], "%"SCNu32, &maxconns)) {
1641 error = ct_dpif_set_maxconns(dpif, maxconns);
1642
1643 if (!error) {
1644 dpctl_print(dpctl_p, "setting maxconns successful");
1645 } else {
1646 dpctl_error(dpctl_p, error, "ct set maxconns failed");
1647 }
1648 } else {
1649 error = EINVAL;
1650 dpctl_error(dpctl_p, error, "maxconns missing or malformed");
1651 }
1652 dpif_close(dpif);
1653 }
1654
1655 return error;
1656}
1657
1658static int
1659dpctl_ct_get_maxconns(int argc, const char *argv[],
1660 struct dpctl_params *dpctl_p)
1661{
1662 struct dpif *dpif;
7cfb862c 1663 int error = opt_dpif_open(argc, argv, dpctl_p, 2, &dpif, NULL);
c92339ad
DB
1664 if (!error) {
1665 uint32_t maxconns;
1666 error = ct_dpif_get_maxconns(dpif, &maxconns);
1667
1668 if (!error) {
1669 dpctl_print(dpctl_p, "%u\n", maxconns);
1670 } else {
1671 dpctl_error(dpctl_p, error, "maxconns could not be retrieved");
1672 }
1673 dpif_close(dpif);
1674 }
1675
1676 return error;
1677}
1678
875075b3
DB
1679static int
1680dpctl_ct_get_nconns(int argc, const char *argv[],
1681 struct dpctl_params *dpctl_p)
1682{
1683 struct dpif *dpif;
7cfb862c 1684 int error = opt_dpif_open(argc, argv, dpctl_p, 2, &dpif, NULL);
875075b3
DB
1685 if (!error) {
1686 uint32_t nconns;
1687 error = ct_dpif_get_nconns(dpif, &nconns);
1688
1689 if (!error) {
1690 dpctl_print(dpctl_p, "%u\n", nconns);
1691 } else {
1692 dpctl_error(dpctl_p, error, "nconns could not be retrieved");
1693 }
1694 dpif_close(dpif);
1695 }
1696
1697 return error;
1698}
1699
fceef209
DDP
1700/* Undocumented commands for unit testing. */
1701
1702static int
1703dpctl_parse_actions(int argc, const char *argv[], struct dpctl_params* dpctl_p)
1704{
1705 int i, error = 0;
1706
1707 for (i = 1; i < argc; i++) {
1708 struct ofpbuf actions;
1709 struct ds s;
1710
1711 ofpbuf_init(&actions, 0);
1712 error = odp_actions_from_string(argv[i], NULL, &actions);
1713
1714 if (error) {
1715 ofpbuf_uninit(&actions);
1716 dpctl_error(dpctl_p, error, "odp_actions_from_string");
1717 return error;
1718 }
1719
1720 ds_init(&s);
0722f341 1721 format_odp_actions(&s, actions.data, actions.size, NULL);
fceef209
DDP
1722 dpctl_print(dpctl_p, "%s\n", ds_cstr(&s));
1723 ds_destroy(&s);
1724
1725 ofpbuf_uninit(&actions);
1726 }
1727
1728 return error;
1729}
1730
1731struct actions_for_flow {
1732 struct hmap_node hmap_node;
1733 struct flow flow;
1734 struct ofpbuf actions;
1735};
1736
1737static struct actions_for_flow *
1738get_actions_for_flow(struct hmap *actions_per_flow, const struct flow *flow)
1739{
1740 uint32_t hash = flow_hash(flow, 0);
1741 struct actions_for_flow *af;
1742
1743 HMAP_FOR_EACH_WITH_HASH (af, hmap_node, hash, actions_per_flow) {
1744 if (flow_equal(&af->flow, flow)) {
1745 return af;
1746 }
1747 }
1748
1749 af = xmalloc(sizeof *af);
1750 af->flow = *flow;
1751 ofpbuf_init(&af->actions, 0);
1752 hmap_insert(actions_per_flow, &af->hmap_node, hash);
1753 return af;
1754}
1755
1756static int
1757compare_actions_for_flow(const void *a_, const void *b_)
1758{
1759 struct actions_for_flow *const *a = a_;
1760 struct actions_for_flow *const *b = b_;
1761
1762 return flow_compare_3way(&(*a)->flow, &(*b)->flow);
1763}
1764
1765static int
1766compare_output_actions(const void *a_, const void *b_)
1767{
1768 const struct nlattr *a = a_;
1769 const struct nlattr *b = b_;
1770 uint32_t a_port = nl_attr_get_u32(a);
1771 uint32_t b_port = nl_attr_get_u32(b);
1772
1773 return a_port < b_port ? -1 : a_port > b_port;
1774}
1775
1776static void
1777sort_output_actions__(struct nlattr *first, struct nlattr *end)
1778{
1779 size_t bytes = (uint8_t *) end - (uint8_t *) first;
1780 size_t n = bytes / NL_A_U32_SIZE;
1781
1782 ovs_assert(bytes % NL_A_U32_SIZE == 0);
1783 qsort(first, n, NL_A_U32_SIZE, compare_output_actions);
1784}
1785
1786static void
1787sort_output_actions(struct nlattr *actions, size_t length)
1788{
1789 struct nlattr *first_output = NULL;
1790 struct nlattr *a;
1791 int left;
1792
1793 NL_ATTR_FOR_EACH (a, left, actions, length) {
1794 if (nl_attr_type(a) == OVS_ACTION_ATTR_OUTPUT) {
1795 if (!first_output) {
1796 first_output = a;
1797 }
1798 } else {
1799 if (first_output) {
1800 sort_output_actions__(first_output, a);
1801 first_output = NULL;
1802 }
1803 }
1804 }
1805 if (first_output) {
1806 uint8_t *end = (uint8_t *) actions + length;
1807 sort_output_actions__(first_output,
1808 ALIGNED_CAST(struct nlattr *, end));
1809 }
1810}
1811
1812/* usage: "ovs-dpctl normalize-actions FLOW ACTIONS" where FLOW and ACTIONS
1813 * have the syntax used by "ovs-dpctl dump-flows".
1814 *
1815 * This command prints ACTIONS in a format that shows what happens for each
1816 * VLAN, independent of the order of the ACTIONS. For example, there is more
1817 * than one way to output a packet on VLANs 9 and 11, but this command will
1818 * print the same output for any form.
1819 *
1820 * The idea here generalizes beyond VLANs (e.g. to setting other fields) but
1821 * so far the implementation only covers VLANs. */
1822static int
1823dpctl_normalize_actions(int argc, const char *argv[],
1824 struct dpctl_params *dpctl_p)
1825{
1826 struct simap port_names;
1827 struct ofpbuf keybuf;
1828 struct flow flow;
1829 struct ofpbuf odp_actions;
1830 struct hmap actions_per_flow;
1831 struct actions_for_flow **afs;
1832 struct actions_for_flow *af;
1833 struct nlattr *a;
1834 size_t n_afs;
1835 struct ds s;
1836 int left;
1837 int i, error;
f0fb825a 1838 int encaps = 0;
fceef209
DDP
1839
1840 ds_init(&s);
1841
1842 simap_init(&port_names);
1843 for (i = 3; i < argc; i++) {
1844 char name[16];
1845 int number;
1846
1847 if (ovs_scan(argv[i], "%15[^=]=%d", name, &number)) {
1848 uintptr_t n = number;
1849 simap_put(&port_names, name, n);
1850 } else {
1851 dpctl_error(dpctl_p, 0, "%s: expected NAME=NUMBER", argv[i]);
1852 error = EINVAL;
1853 goto out;
1854 }
1855 }
1856
1857 /* Parse flow key. */
1858 ofpbuf_init(&keybuf, 0);
1859 error = odp_flow_from_string(argv[1], &port_names, &keybuf, NULL);
1860 if (error) {
1861 dpctl_error(dpctl_p, error, "odp_flow_key_from_string");
1862 goto out_freekeybuf;
1863 }
1864
1865 ds_clear(&s);
6fd6ed71 1866 odp_flow_format(keybuf.data, keybuf.size, NULL, 0, NULL,
fceef209
DDP
1867 &s, dpctl_p->verbosity);
1868 dpctl_print(dpctl_p, "input flow: %s\n", ds_cstr(&s));
1869
6fd6ed71 1870 error = odp_flow_key_to_flow(keybuf.data, keybuf.size, &flow);
fceef209
DDP
1871 if (error) {
1872 dpctl_error(dpctl_p, error, "odp_flow_key_to_flow");
1873 goto out_freekeybuf;
1874 }
1875
1876 /* Parse actions. */
1877 ofpbuf_init(&odp_actions, 0);
1878 error = odp_actions_from_string(argv[2], &port_names, &odp_actions);
1879 if (error) {
1880 dpctl_error(dpctl_p, error, "odp_actions_from_string");
1881 goto out_freeactions;
1882 }
1883
1884 if (dpctl_p->verbosity) {
1885 ds_clear(&s);
0722f341 1886 format_odp_actions(&s, odp_actions.data, odp_actions.size, NULL);
fceef209
DDP
1887 dpctl_print(dpctl_p, "input actions: %s\n", ds_cstr(&s));
1888 }
1889
1890 hmap_init(&actions_per_flow);
6fd6ed71 1891 NL_ATTR_FOR_EACH (a, left, odp_actions.data, odp_actions.size) {
fceef209
DDP
1892 const struct ovs_action_push_vlan *push;
1893 switch(nl_attr_type(a)) {
1894 case OVS_ACTION_ATTR_POP_VLAN:
f0fb825a 1895 flow_pop_vlan(&flow, NULL);
fceef209
DDP
1896 continue;
1897
1898 case OVS_ACTION_ATTR_PUSH_VLAN:
f0fb825a 1899 flow_push_vlan_uninit(&flow, NULL);
fceef209 1900 push = nl_attr_get_unspec(a, sizeof *push);
f0fb825a
EG
1901 flow.vlans[0].tpid = push->vlan_tpid;
1902 flow.vlans[0].tci = push->vlan_tci;
fceef209
DDP
1903 continue;
1904 }
1905
1906 af = get_actions_for_flow(&actions_per_flow, &flow);
1907 nl_msg_put_unspec(&af->actions, nl_attr_type(a),
1908 nl_attr_get(a), nl_attr_get_size(a));
1909 }
1910
1911 n_afs = hmap_count(&actions_per_flow);
1912 afs = xmalloc(n_afs * sizeof *afs);
1913 i = 0;
1914 HMAP_FOR_EACH (af, hmap_node, &actions_per_flow) {
1915 afs[i++] = af;
1916 }
1917
1918 ovs_assert(i == n_afs);
1919 hmap_destroy(&actions_per_flow);
1920
1921 qsort(afs, n_afs, sizeof *afs, compare_actions_for_flow);
1922
1923 for (i = 0; i < n_afs; i++) {
71f21279 1924 af = afs[i];
6fd6ed71 1925 sort_output_actions(af->actions.data, af->actions.size);
fceef209 1926
f0fb825a
EG
1927 for (encaps = 0; encaps < FLOW_MAX_VLAN_HEADERS; encaps ++) {
1928 union flow_vlan_hdr *vlan = &af->flow.vlans[encaps];
1929 if (vlan->tci != htons(0)) {
1930 dpctl_print(dpctl_p, "vlan(");
1931 if (vlan->tpid != htons(ETH_TYPE_VLAN)) {
1932 dpctl_print(dpctl_p, "tpid=0x%04"PRIx16",", vlan->tpid);
1933 }
1934 dpctl_print(dpctl_p, "vid=%"PRIu16",pcp=%d): ",
1935 vlan_tci_to_vid(vlan->tci),
1936 vlan_tci_to_pcp(vlan->tci));
1937 } else {
1938 if (encaps == 0) {
1939 dpctl_print(dpctl_p, "no vlan: ");
1940 }
1941 break;
1942 }
fceef209
DDP
1943 }
1944
1945 if (eth_type_mpls(af->flow.dl_type)) {
1946 dpctl_print(dpctl_p, "mpls(label=%"PRIu32",tc=%d,ttl=%d): ",
1947 mpls_lse_to_label(af->flow.mpls_lse[0]),
1948 mpls_lse_to_tc(af->flow.mpls_lse[0]),
1949 mpls_lse_to_ttl(af->flow.mpls_lse[0]));
1950 } else {
1951 dpctl_print(dpctl_p, "no mpls: ");
1952 }
1953
1954 ds_clear(&s);
0722f341 1955 format_odp_actions(&s, af->actions.data, af->actions.size, NULL);
7521b9e5 1956 dpctl_puts(dpctl_p, false, ds_cstr(&s));
fceef209
DDP
1957
1958 ofpbuf_uninit(&af->actions);
1959 free(af);
1960 }
1961 free(afs);
1962
1963
1964out_freeactions:
1965 ofpbuf_uninit(&odp_actions);
1966out_freekeybuf:
1967 ofpbuf_uninit(&keybuf);
1968out:
1969 simap_destroy(&port_names);
1970 ds_destroy(&s);
1971
1972 return error;
1973}
1974\f
fceef209 1975static const struct dpctl_command all_commands[] = {
1ed90a98
BP
1976 { "add-dp", "dp [iface...]", 1, INT_MAX, dpctl_add_dp, DP_RW },
1977 { "del-dp", "dp", 1, 1, dpctl_del_dp, DP_RW },
1978 { "add-if", "dp iface...", 2, INT_MAX, dpctl_add_if, DP_RW },
1979 { "del-if", "dp iface...", 2, INT_MAX, dpctl_del_if, DP_RW },
1980 { "set-if", "dp iface...", 2, INT_MAX, dpctl_set_if, DP_RW },
1f4a7252
RM
1981 { "dump-dps", "", 0, 0, dpctl_dump_dps, DP_RO },
1982 { "show", "[dp...]", 0, INT_MAX, dpctl_show, DP_RO },
1401f6de
FA
1983 { "dump-flows", "[dp] [filter=..] [type=..]",
1984 0, 3, dpctl_dump_flows, DP_RO },
1ed90a98
BP
1985 { "add-flow", "[dp] flow actions", 2, 3, dpctl_add_flow, DP_RW },
1986 { "mod-flow", "[dp] flow actions", 2, 3, dpctl_mod_flow, DP_RW },
1987 { "get-flow", "[dp] ufid", 1, 2, dpctl_get_flow, DP_RO },
1988 { "del-flow", "[dp] flow", 1, 2, dpctl_del_flow, DP_RW },
1f4a7252
RM
1989 { "del-flows", "[dp]", 0, 1, dpctl_del_flows, DP_RW },
1990 { "dump-conntrack", "[dp] [zone=N]", 0, 2, dpctl_dump_conntrack, DP_RO },
c43a1331
YHW
1991 { "flush-conntrack", "[dp] [zone=N] [ct-tuple]", 0, 3,
1992 dpctl_flush_conntrack, DP_RW },
16b361ef 1993 { "ct-stats-show", "[dp] [zone=N]",
8a0d9d85 1994 0, 3, dpctl_ct_stats_show, DP_RO },
ded30c74 1995 { "ct-bkts", "[dp] [gt=N]", 0, 2, dpctl_ct_bkts, DP_RO },
c92339ad
DB
1996 { "ct-set-maxconns", "[dp] maxconns", 1, 2, dpctl_ct_set_maxconns, DP_RW },
1997 { "ct-get-maxconns", "[dp]", 0, 1, dpctl_ct_get_maxconns, DP_RO },
875075b3 1998 { "ct-get-nconns", "[dp]", 0, 1, dpctl_ct_get_nconns, DP_RO },
1f4a7252
RM
1999 { "help", "", 0, INT_MAX, dpctl_help, DP_RO },
2000 { "list-commands", "", 0, INT_MAX, dpctl_list_commands, DP_RO },
fceef209
DDP
2001
2002 /* Undocumented commands for testing. */
1f4a7252 2003 { "parse-actions", "actions", 1, INT_MAX, dpctl_parse_actions, DP_RO },
1401f6de
FA
2004 { "normalize-actions", "actions",
2005 2, INT_MAX, dpctl_normalize_actions, DP_RO },
fceef209 2006
1f4a7252 2007 { NULL, NULL, 0, 0, NULL, DP_RO },
fceef209
DDP
2008};
2009
56cad666
AW
2010static const struct dpctl_command *get_all_dpctl_commands(void)
2011{
2012 return all_commands;
2013}
2014
fceef209
DDP
2015/* Runs the command designated by argv[0] within the command table specified by
2016 * 'commands', which must be terminated by a command whose 'name' member is a
2017 * null pointer. */
2018int
2019dpctl_run_command(int argc, const char *argv[], struct dpctl_params *dpctl_p)
2020{
2021 const struct dpctl_command *p;
fceef209
DDP
2022 if (argc < 1) {
2023 dpctl_error(dpctl_p, 0, "missing command name; use --help for help");
2024 return EINVAL;
2025 }
2026
2027 for (p = all_commands; p->name != NULL; p++) {
2028 if (!strcmp(p->name, argv[0])) {
2029 int n_arg = argc - 1;
2030 if (n_arg < p->min_args) {
2031 dpctl_error(dpctl_p, 0,
2032 "'%s' command requires at least %d arguments",
2033 p->name, p->min_args);
2034 return EINVAL;
2035 } else if (n_arg > p->max_args) {
2036 dpctl_error(dpctl_p, 0,
2037 "'%s' command takes at most %d arguments",
2038 p->name, p->max_args);
2039 return EINVAL;
2040 } else {
1f4a7252
RM
2041 if (p->mode == DP_RW && dpctl_p->read_only) {
2042 dpctl_error(dpctl_p, 0,
2043 "'%s' command does not work in read only mode",
2044 p->name);
2045 return EINVAL;
2046 }
fceef209
DDP
2047 return p->handler(argc, argv, dpctl_p);
2048 }
2049 }
2050 }
2051
2052 dpctl_error(dpctl_p, 0, "unknown command '%s'; use --help for help",
2053 argv[0]);
2054 return EINVAL;
2055}
2056\f
2057static void
2058dpctl_unixctl_print(void *userdata, bool error OVS_UNUSED, const char *msg)
2059{
2060 struct ds *ds = userdata;
2061 ds_put_cstr(ds, msg);
2062}
2063
2064static void
2065dpctl_unixctl_handler(struct unixctl_conn *conn, int argc, const char *argv[],
2066 void *aux)
2067{
2068 struct ds ds = DS_EMPTY_INITIALIZER;
79ae214d 2069 bool error = false;
fceef209 2070
337c4528
BP
2071 struct dpctl_params dpctl_p = {
2072 .is_appctl = true,
2073 .output = dpctl_unixctl_print,
2074 .aux = &ds,
2075 };
fceef209
DDP
2076
2077 /* Parse options (like getopt). Unfortunately it does
2078 * not seem a good idea to call getopt_long() here, since it uses global
2079 * variables */
d1fd1ea9 2080 bool set_names = false;
79ae214d 2081 while (argc > 1 && !error) {
fceef209
DDP
2082 const char *arg = argv[1];
2083 if (!strncmp(arg, "--", 2)) {
2084 /* Long option */
2085 if (!strcmp(arg, "--statistics")) {
2086 dpctl_p.print_statistics = true;
2087 } else if (!strcmp(arg, "--clear")) {
2088 dpctl_p.zero_statistics = true;
2089 } else if (!strcmp(arg, "--may-create")) {
2090 dpctl_p.may_create = true;
2091 } else if (!strcmp(arg, "--more")) {
2092 dpctl_p.verbosity++;
d1fd1ea9
BP
2093 } else if (!strcmp(arg, "--names")) {
2094 dpctl_p.names = true;
2095 set_names = true;
2096 } else if (!strcmp(arg, "--no-names")) {
2097 dpctl_p.names = false;
2098 set_names = true;
fceef209
DDP
2099 } else {
2100 ds_put_format(&ds, "Unrecognized option %s", argv[1]);
79ae214d 2101 error = true;
fceef209
DDP
2102 }
2103 } else if (arg[0] == '-' && arg[1] != '\0') {
2104 /* Short option[s] */
2105 const char *opt = &arg[1];
2106
79ae214d 2107 while (*opt && !error) {
fceef209
DDP
2108 switch (*opt) {
2109 case 'm':
2110 dpctl_p.verbosity++;
2111 break;
2112 case 's':
2113 dpctl_p.print_statistics = true;
2114 break;
2115 default:
2116 ds_put_format(&ds, "Unrecognized option -%c", *opt);
79ae214d 2117 error = true;
fceef209
DDP
2118 break;
2119 }
2120 opt++;
2121 }
2122 } else {
2123 /* Doesn't start with -, not an option */
2124 break;
2125 }
2126
79ae214d 2127 if (error) {
fceef209
DDP
2128 break;
2129 }
2130 argv++;
2131 argc--;
2132 }
d1fd1ea9
BP
2133 if (!set_names) {
2134 dpctl_p.names = dpctl_p.verbosity > 0;
2135 }
2136 VLOG_INFO("set_names=%d verbosity=%d names=%d", set_names,
2137 dpctl_p.verbosity, dpctl_p.names);
fceef209 2138
79ae214d 2139 if (!error) {
337c4528 2140 dpctl_command_handler *handler = (dpctl_command_handler *) aux;
79ae214d 2141 error = handler(argc, argv, &dpctl_p) != 0;
fceef209
DDP
2142 }
2143
79ae214d
BP
2144 if (error) {
2145 unixctl_command_reply_error(conn, ds_cstr(&ds));
2146 } else {
2147 unixctl_command_reply(conn, ds_cstr(&ds));
2148 }
fceef209
DDP
2149
2150 ds_destroy(&ds);
2151}
2152
2153void
2154dpctl_unixctl_register(void)
2155{
2156 const struct dpctl_command *p;
2157
2158 for (p = all_commands; p->name != NULL; p++) {
337c4528
BP
2159 if (strcmp(p->name, "help")) {
2160 char *cmd_name = xasprintf("dpctl/%s", p->name);
c0297846 2161 unixctl_command_register(cmd_name,
2162 p->usage,
2163 p->min_args,
2164 p->max_args,
2165 dpctl_unixctl_handler,
2166 p->handler);
337c4528
BP
2167 free(cmd_name);
2168 }
fceef209
DDP
2169 }
2170}