]> git.proxmox.com Git - mirror_ovs.git/blob - lib/dpctl.c
treewide: Clean up inclusions of netdev-dpdk header.
[mirror_ovs.git] / lib / dpctl.c
1 /*
2 * Copyright (c) 2008-2019 Nicira, Inc.
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>
18 #include <sys/types.h>
19 #include <netinet/in.h>
20 #include <arpa/inet.h>
21 #include <errno.h>
22 #include <inttypes.h>
23 #include <sys/socket.h>
24 #include <net/if.h>
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"
32 #include "ct-dpif.h"
33 #include "dirs.h"
34 #include "dpctl.h"
35 #include "dpif.h"
36 #include "dpif-provider.h"
37 #include "openvswitch/dynamic-string.h"
38 #include "flow.h"
39 #include "openvswitch/match.h"
40 #include "netdev.h"
41 #include "netlink.h"
42 #include "odp-util.h"
43 #include "openvswitch/ofpbuf.h"
44 #include "packets.h"
45 #include "openvswitch/shash.h"
46 #include "simap.h"
47 #include "smap.h"
48 #include "sset.h"
49 #include "timeval.h"
50 #include "unixctl.h"
51 #include "util.h"
52 #include "openvswitch/ofp-flow.h"
53 #include "openvswitch/ofp-port.h"
54 #include "openvswitch/vlog.h"
55 VLOG_DEFINE_THIS_MODULE(dpctl);
56
57 typedef int dpctl_command_handler(int argc, const char *argv[],
58 struct dpctl_params *);
59 struct dpctl_command {
60 const char *name;
61 const char *usage;
62 int min_args;
63 int max_args;
64 dpctl_command_handler *handler;
65 enum { DP_RO, DP_RW} mode;
66 };
67 static const struct dpctl_command *get_all_dpctl_commands(void);
68 static void dpctl_print(struct dpctl_params *dpctl_p, const char *fmt, ...)
69 OVS_PRINTF_FORMAT(2, 3);
70 static void dpctl_error(struct dpctl_params* dpctl_p, int err_no,
71 const char *fmt, ...)
72 OVS_PRINTF_FORMAT(3, 4);
73
74 static void
75 dpctl_puts(struct dpctl_params *dpctl_p, bool error, const char *string)
76 {
77 dpctl_p->output(dpctl_p->aux, error, string);
78 }
79
80 static void
81 dpctl_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
94 static void
95 dpctl_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
125 static int dpctl_add_if(int argc, const char *argv[], struct dpctl_params *);
126
127 static int
128 if_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
134 * is responsible for freeing the returned string. If a single datapath
135 * name cannot be determined, returns NULL. */
136 static char *
137 get_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
171 static int
172 parsed_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
190 static bool
191 dp_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 free(queried_name);
206 free(queried_type);
207 return found;
208 }
209
210 static bool
211 dp_arg_exists(int argc, const char *argv[])
212 {
213 return argc > 1 && dp_exists(argv[1]);
214 }
215
216 /* Open a dpif with an optional name argument.
217 *
218 * The datapath name is not a mandatory parameter for this command. If it is
219 * not specified, we retrieve it from the current setup, assuming only one
220 * exists. On success stores the opened dpif in '*dpifp'. */
221 static int
222 opt_dpif_open(int argc, const char *argv[], struct dpctl_params *dpctl_p,
223 int max_args, struct dpif **dpifp)
224 {
225 char *dpname;
226
227 if (dp_arg_exists(argc, argv)) {
228 dpname = xstrdup(argv[1]);
229 } else if (argc != max_args) {
230 dpname = get_one_dp(dpctl_p);
231 } else {
232 /* If the arguments are the maximum possible number and there is no
233 * valid datapath argument, then we fall into the case of dpname is
234 * NULL, since this is an error. */
235 dpname = NULL;
236 }
237
238 int error = 0;
239 if (!dpname) {
240 error = EINVAL;
241 dpctl_error(dpctl_p, error, "datapath not found");
242 } else {
243 error = parsed_dpif_open(dpname, false, dpifp);
244 free(dpname);
245 if (error) {
246 dpctl_error(dpctl_p, error, "opening datapath");
247 }
248 }
249 return error;
250 }
251
252 static int
253 dpctl_add_dp(int argc, const char *argv[],
254 struct dpctl_params *dpctl_p)
255 {
256 struct dpif *dpif;
257 int error;
258
259 error = parsed_dpif_open(argv[1], true, &dpif);
260 if (error) {
261 dpctl_error(dpctl_p, error, "add_dp");
262 return error;
263 }
264 dpif_close(dpif);
265 if (argc > 2) {
266 error = dpctl_add_if(argc, argv, dpctl_p);
267 }
268 return error;
269 }
270
271 static int
272 dpctl_del_dp(int argc OVS_UNUSED, const char *argv[],
273 struct dpctl_params *dpctl_p)
274 {
275 struct dpif *dpif;
276 int error;
277
278 error = parsed_dpif_open(argv[1], false, &dpif);
279 if (error) {
280 dpctl_error(dpctl_p, error, "opening datapath");
281 return error;
282 }
283 error = dpif_delete(dpif);
284 if (error) {
285 dpctl_error(dpctl_p, error, "del_dp");
286 }
287
288 dpif_close(dpif);
289 return error;
290 }
291
292 static int
293 dpctl_add_if(int argc OVS_UNUSED, const char *argv[],
294 struct dpctl_params *dpctl_p)
295 {
296 struct dpif *dpif;
297 int i, error, lasterror = 0;
298
299 error = parsed_dpif_open(argv[1], false, &dpif);
300 if (error) {
301 dpctl_error(dpctl_p, error, "opening datapath");
302 return error;
303 }
304 for (i = 2; i < argc; i++) {
305 const char *name, *type;
306 char *save_ptr = NULL, *argcopy;
307 struct netdev *netdev = NULL;
308 struct smap args;
309 odp_port_t port_no = ODPP_NONE;
310 char *option;
311
312 argcopy = xstrdup(argv[i]);
313 name = strtok_r(argcopy, ",", &save_ptr);
314 type = "system";
315
316 if (!name) {
317 dpctl_error(dpctl_p, 0, "%s is not a valid network device name",
318 argv[i]);
319 error = EINVAL;
320 goto next;
321 }
322
323 smap_init(&args);
324 while ((option = strtok_r(NULL, ",", &save_ptr)) != NULL) {
325 char *save_ptr_2 = NULL;
326 char *key, *value;
327
328 key = strtok_r(option, "=", &save_ptr_2);
329 value = strtok_r(NULL, "", &save_ptr_2);
330 if (!value) {
331 value = "";
332 }
333
334 if (!strcmp(key, "type")) {
335 type = value;
336 } else if (!strcmp(key, "port_no")) {
337 port_no = u32_to_odp(atoi(value));
338 } else if (!smap_add_once(&args, key, value)) {
339 dpctl_error(dpctl_p, 0, "duplicate \"%s\" option", key);
340 }
341 }
342
343 error = netdev_open(name, type, &netdev);
344 if (error) {
345 dpctl_error(dpctl_p, error, "%s: failed to open network device",
346 name);
347 goto next_destroy_args;
348 }
349
350 error = netdev_set_config(netdev, &args, NULL);
351 if (error) {
352 goto next_destroy_args;
353 }
354
355 error = dpif_port_add(dpif, netdev, &port_no);
356 if (error) {
357 dpctl_error(dpctl_p, error, "adding %s to %s failed", name,
358 argv[1]);
359 goto next_destroy_args;
360 }
361
362 error = if_up(netdev);
363 if (error) {
364 dpctl_error(dpctl_p, error, "%s: failed bringing interface up",
365 name);
366 }
367
368 next_destroy_args:
369 netdev_close(netdev);
370 smap_destroy(&args);
371 next:
372 free(argcopy);
373 if (error) {
374 lasterror = error;
375 }
376 }
377 dpif_close(dpif);
378
379 return lasterror;
380 }
381
382 static int
383 dpctl_set_if(int argc, const char *argv[], struct dpctl_params *dpctl_p)
384 {
385 struct dpif *dpif;
386 int i, error, lasterror = 0;
387
388 error = parsed_dpif_open(argv[1], false, &dpif);
389 if (error) {
390 dpctl_error(dpctl_p, error, "opening datapath");
391 return error;
392 }
393 for (i = 2; i < argc; i++) {
394 struct netdev *netdev = NULL;
395 struct dpif_port dpif_port;
396 char *save_ptr = NULL;
397 char *type = NULL;
398 char *argcopy;
399 const char *name;
400 struct smap args;
401 odp_port_t port_no;
402 char *option;
403
404 error = 0;
405
406 argcopy = xstrdup(argv[i]);
407 name = strtok_r(argcopy, ",", &save_ptr);
408 if (!name) {
409 dpctl_error(dpctl_p, 0, "%s is not a valid network device name",
410 argv[i]);
411 goto next;
412 }
413
414 /* Get the port's type from the datapath. */
415 error = dpif_port_query_by_name(dpif, name, &dpif_port);
416 if (error) {
417 dpctl_error(dpctl_p, error, "%s: failed to query port in %s", name,
418 argv[1]);
419 goto next;
420 }
421 type = xstrdup(dpif_port.type);
422 port_no = dpif_port.port_no;
423 dpif_port_destroy(&dpif_port);
424
425 /* Retrieve its existing configuration. */
426 error = netdev_open(name, type, &netdev);
427 if (error) {
428 dpctl_error(dpctl_p, error, "%s: failed to open network device",
429 name);
430 goto next;
431 }
432
433 smap_init(&args);
434 error = netdev_get_config(netdev, &args);
435 if (error) {
436 dpctl_error(dpctl_p, error, "%s: failed to fetch configuration",
437 name);
438 goto next_destroy_args;
439 }
440
441 /* Parse changes to configuration. */
442 while ((option = strtok_r(NULL, ",", &save_ptr)) != NULL) {
443 char *save_ptr_2 = NULL;
444 char *key, *value;
445
446 key = strtok_r(option, "=", &save_ptr_2);
447 value = strtok_r(NULL, "", &save_ptr_2);
448 if (!value) {
449 value = "";
450 }
451
452 if (!strcmp(key, "type")) {
453 if (strcmp(value, type)) {
454 dpctl_error(dpctl_p, 0,
455 "%s: can't change type from %s to %s",
456 name, type, value);
457 error = EINVAL;
458 goto next_destroy_args;
459 }
460 } else if (!strcmp(key, "port_no")) {
461 if (port_no != u32_to_odp(atoi(value))) {
462 dpctl_error(dpctl_p, 0, "%s: can't change port number from"
463 " %"PRIu32" to %d", name, port_no, atoi(value));
464 error = EINVAL;
465 goto next_destroy_args;
466 }
467 } else if (value[0] == '\0') {
468 smap_remove(&args, key);
469 } else {
470 smap_replace(&args, key, value);
471 }
472 }
473
474 /* Update configuration. */
475 char *err_s = NULL;
476 error = netdev_set_config(netdev, &args, &err_s);
477 if (err_s || error) {
478 dpctl_error(dpctl_p, error, "%s",
479 err_s ? err_s : "Error updating configuration");
480 free(err_s);
481 }
482 if (error) {
483 goto next_destroy_args;
484 }
485
486 next_destroy_args:
487 smap_destroy(&args);
488 next:
489 netdev_close(netdev);
490 free(type);
491 free(argcopy);
492 if (error) {
493 lasterror = error;
494 }
495 }
496 dpif_close(dpif);
497
498 return lasterror;
499 }
500
501 static bool
502 get_port_number(struct dpif *dpif, const char *name, odp_port_t *port,
503 struct dpctl_params *dpctl_p)
504 {
505 struct dpif_port dpif_port;
506
507 if (!dpif_port_query_by_name(dpif, name, &dpif_port)) {
508 *port = dpif_port.port_no;
509 dpif_port_destroy(&dpif_port);
510 return true;
511 } else {
512 dpctl_error(dpctl_p, 0, "no port named %s", name);
513 return false;
514 }
515 }
516
517 static int
518 dpctl_del_if(int argc, const char *argv[], struct dpctl_params *dpctl_p)
519 {
520 struct dpif *dpif;
521 int i, error, lasterror = 0;
522
523 error = parsed_dpif_open(argv[1], false, &dpif);
524 if (error) {
525 dpctl_error(dpctl_p, error, "opening datapath");
526 return error;
527 }
528 for (i = 2; i < argc; i++) {
529 const char *name = argv[i];
530 odp_port_t port;
531
532 if (!name[strspn(name, "0123456789")]) {
533 port = u32_to_odp(atoi(name));
534 } else if (!get_port_number(dpif, name, &port, dpctl_p)) {
535 lasterror = ENOENT;
536 continue;
537 }
538
539 error = dpif_port_del(dpif, port, false);
540 if (error) {
541 dpctl_error(dpctl_p, error, "deleting port %s from %s failed",
542 name, argv[1]);
543 lasterror = error;
544 }
545 }
546 dpif_close(dpif);
547 return lasterror;
548 }
549
550 static void
551 print_stat(struct dpctl_params *dpctl_p, const char *leader, uint64_t value)
552 {
553 dpctl_print(dpctl_p, "%s", leader);
554 if (value != UINT64_MAX) {
555 dpctl_print(dpctl_p, "%"PRIu64, value);
556 } else {
557 dpctl_print(dpctl_p, "?");
558 }
559 }
560
561 static void
562 print_human_size(struct dpctl_params *dpctl_p, uint64_t value)
563 {
564 if (value == UINT64_MAX) {
565 /* Nothing to do. */
566 } else if (value >= 1024ULL * 1024 * 1024 * 1024) {
567 dpctl_print(dpctl_p, " (%.1f TiB)",
568 value / (1024.0 * 1024 * 1024 * 1024));
569 } else if (value >= 1024ULL * 1024 * 1024) {
570 dpctl_print(dpctl_p, " (%.1f GiB)", value / (1024.0 * 1024 * 1024));
571 } else if (value >= 1024ULL * 1024) {
572 dpctl_print(dpctl_p, " (%.1f MiB)", value / (1024.0 * 1024));
573 } else if (value >= 1024) {
574 dpctl_print(dpctl_p, " (%.1f KiB)", value / 1024.0);
575 }
576 }
577
578 /* qsort comparison function. */
579 static int
580 compare_port_nos(const void *a_, const void *b_)
581 {
582 const odp_port_t *ap = a_;
583 const odp_port_t *bp = b_;
584 uint32_t a = odp_to_u32(*ap);
585 uint32_t b = odp_to_u32(*bp);
586
587 return a < b ? -1 : a > b;
588 }
589
590 static void
591 show_dpif(struct dpif *dpif, struct dpctl_params *dpctl_p)
592 {
593 struct dpif_port_dump dump;
594 struct dpif_port dpif_port;
595 struct dpif_dp_stats stats;
596 struct netdev *netdev;
597
598 dpctl_print(dpctl_p, "%s:\n", dpif_name(dpif));
599 if (!dpif_get_dp_stats(dpif, &stats)) {
600 dpctl_print(dpctl_p, " lookups: hit:%"PRIu64" missed:%"PRIu64
601 " lost:%"PRIu64"\n flows: %"PRIu64"\n",
602 stats.n_hit, stats.n_missed, stats.n_lost, stats.n_flows);
603 if (stats.n_masks != UINT32_MAX) {
604 uint64_t n_pkts = stats.n_hit + stats.n_missed;
605 double avg = n_pkts ? (double) stats.n_mask_hit / n_pkts : 0.0;
606
607 dpctl_print(dpctl_p, " masks: hit:%"PRIu64" total:%"PRIu32
608 " hit/pkt:%.2f\n",
609 stats.n_mask_hit, stats.n_masks, avg);
610 }
611 }
612
613 odp_port_t *port_nos = NULL;
614 size_t allocated_port_nos = 0, n_port_nos = 0;
615 DPIF_PORT_FOR_EACH (&dpif_port, &dump, dpif) {
616 if (n_port_nos >= allocated_port_nos) {
617 port_nos = x2nrealloc(port_nos, &allocated_port_nos,
618 sizeof *port_nos);
619 }
620
621 port_nos[n_port_nos] = dpif_port.port_no;
622 n_port_nos++;
623 }
624
625 if (port_nos) {
626 qsort(port_nos, n_port_nos, sizeof *port_nos, compare_port_nos);
627 }
628
629 for (int i = 0; i < n_port_nos; i++) {
630 if (dpif_port_query_by_number(dpif, port_nos[i], &dpif_port)) {
631 continue;
632 }
633
634 dpctl_print(dpctl_p, " port %u: %s",
635 dpif_port.port_no, dpif_port.name);
636
637 if (strcmp(dpif_port.type, "system")) {
638 int error;
639
640 dpctl_print(dpctl_p, " (%s", dpif_port.type);
641
642 error = netdev_open(dpif_port.name, dpif_port.type, &netdev);
643 if (!error) {
644 struct smap config;
645
646 smap_init(&config);
647 error = netdev_get_config(netdev, &config);
648 if (!error) {
649 const struct smap_node **nodes = smap_sort(&config);
650 for (size_t j = 0; j < smap_count(&config); j++) {
651 const struct smap_node *node = nodes[j];
652 dpctl_print(dpctl_p, "%c %s=%s", j ? ',' : ':',
653 node->key, node->value);
654 }
655 free(nodes);
656 } else {
657 dpctl_print(dpctl_p, ", could not retrieve configuration "
658 "(%s)", ovs_strerror(error));
659 }
660 smap_destroy(&config);
661
662 netdev_close(netdev);
663 } else {
664 dpctl_print(dpctl_p, ": open failed (%s)",
665 ovs_strerror(error));
666 }
667 dpctl_print(dpctl_p, ")");
668 }
669 dpctl_print(dpctl_p, "\n");
670
671 if (dpctl_p->print_statistics) {
672 struct netdev_stats s;
673 int error;
674
675 error = netdev_open(dpif_port.name, dpif_port.type, &netdev);
676 if (error) {
677 dpctl_print(dpctl_p, ", open failed (%s)",
678 ovs_strerror(error));
679 dpif_port_destroy(&dpif_port);
680 continue;
681 }
682 error = netdev_get_stats(netdev, &s);
683 if (!error) {
684 netdev_close(netdev);
685 print_stat(dpctl_p, " RX packets:", s.rx_packets);
686 print_stat(dpctl_p, " errors:", s.rx_errors);
687 print_stat(dpctl_p, " dropped:", s.rx_dropped);
688 print_stat(dpctl_p, " overruns:", s.rx_over_errors);
689 print_stat(dpctl_p, " frame:", s.rx_frame_errors);
690 dpctl_print(dpctl_p, "\n");
691
692 print_stat(dpctl_p, " TX packets:", s.tx_packets);
693 print_stat(dpctl_p, " errors:", s.tx_errors);
694 print_stat(dpctl_p, " dropped:", s.tx_dropped);
695 print_stat(dpctl_p, " aborted:", s.tx_aborted_errors);
696 print_stat(dpctl_p, " carrier:", s.tx_carrier_errors);
697 dpctl_print(dpctl_p, "\n");
698
699 print_stat(dpctl_p, " collisions:", s.collisions);
700 dpctl_print(dpctl_p, "\n");
701
702 print_stat(dpctl_p, " RX bytes:", s.rx_bytes);
703 print_human_size(dpctl_p, s.rx_bytes);
704 print_stat(dpctl_p, " TX bytes:", s.tx_bytes);
705 print_human_size(dpctl_p, s.tx_bytes);
706 dpctl_print(dpctl_p, "\n");
707 } else {
708 dpctl_print(dpctl_p, ", could not retrieve stats (%s)",
709 ovs_strerror(error));
710 }
711 }
712 dpif_port_destroy(&dpif_port);
713 }
714
715 free(port_nos);
716 }
717
718 typedef void (*dps_for_each_cb)(struct dpif *, struct dpctl_params *);
719
720 static int
721 dps_for_each(struct dpctl_params *dpctl_p, dps_for_each_cb cb)
722 {
723 struct sset dpif_names = SSET_INITIALIZER(&dpif_names),
724 dpif_types = SSET_INITIALIZER(&dpif_types);
725 int error, openerror = 0, enumerror = 0;
726 const char *type, *name;
727 bool at_least_one = false;
728
729 dp_enumerate_types(&dpif_types);
730
731 SSET_FOR_EACH (type, &dpif_types) {
732 error = dp_enumerate_names(type, &dpif_names);
733 if (error) {
734 enumerror = error;
735 }
736
737 SSET_FOR_EACH (name, &dpif_names) {
738 struct dpif *dpif;
739
740 at_least_one = true;
741 error = dpif_open(name, type, &dpif);
742 if (!error) {
743 cb(dpif, dpctl_p);
744 dpif_close(dpif);
745 } else {
746 openerror = error;
747 dpctl_error(dpctl_p, error, "opening datapath %s failed",
748 name);
749 }
750 }
751 }
752
753 sset_destroy(&dpif_names);
754 sset_destroy(&dpif_types);
755
756 /* If there has been an error while opening a datapath it should be
757 * reported. Otherwise, we want to ignore the errors generated by
758 * dp_enumerate_names() if at least one datapath has been discovered,
759 * because they're not interesting for the user. This happens, for
760 * example, if OVS is using a userspace datapath and the kernel module
761 * is not loaded. */
762 if (openerror) {
763 return openerror;
764 } else {
765 return at_least_one ? 0 : enumerror;
766 }
767 }
768
769 static int
770 dpctl_show(int argc, const char *argv[], struct dpctl_params *dpctl_p)
771 {
772 int error, lasterror = 0;
773 if (argc > 1) {
774 int i;
775 for (i = 1; i < argc; i++) {
776 const char *name = argv[i];
777 struct dpif *dpif;
778
779 error = parsed_dpif_open(name, false, &dpif);
780 if (!error) {
781 show_dpif(dpif, dpctl_p);
782 dpif_close(dpif);
783 } else {
784 dpctl_error(dpctl_p, error, "opening datapath %s failed",
785 name);
786 lasterror = error;
787 }
788 }
789 } else {
790 lasterror = dps_for_each(dpctl_p, show_dpif);
791 }
792
793 return lasterror;
794 }
795
796 static void
797 dump_cb(struct dpif *dpif, struct dpctl_params *dpctl_p)
798 {
799 dpctl_print(dpctl_p, "%s\n", dpif_name(dpif));
800 }
801
802 static int
803 dpctl_dump_dps(int argc OVS_UNUSED, const char *argv[] OVS_UNUSED,
804 struct dpctl_params *dpctl_p)
805 {
806 return dps_for_each(dpctl_p, dump_cb);
807 }
808
809 static void
810 format_dpif_flow(struct ds *ds, const struct dpif_flow *f, struct hmap *ports,
811 struct dpctl_params *dpctl_p)
812 {
813 if (dpctl_p->verbosity && f->ufid_present) {
814 odp_format_ufid(&f->ufid, ds);
815 ds_put_cstr(ds, ", ");
816 }
817 odp_flow_format(f->key, f->key_len, f->mask, f->mask_len, ports, ds,
818 dpctl_p->verbosity);
819 ds_put_cstr(ds, ", ");
820
821 dpif_flow_stats_format(&f->stats, ds);
822 if (dpctl_p->verbosity && f->attrs.offloaded) {
823 ds_put_cstr(ds, ", offloaded:yes");
824 }
825 if (dpctl_p->verbosity && f->attrs.dp_layer) {
826 ds_put_format(ds, ", dp:%s", f->attrs.dp_layer);
827 }
828 ds_put_cstr(ds, ", actions:");
829 format_odp_actions(ds, f->actions, f->actions_len, ports);
830 }
831
832 struct dump_types {
833 bool ovs;
834 bool tc;
835 bool offloaded;
836 bool non_offloaded;
837 };
838
839 static void
840 enable_all_dump_types(struct dump_types *dump_types)
841 {
842 dump_types->ovs = true;
843 dump_types->tc = true;
844 dump_types->offloaded = true;
845 dump_types->non_offloaded = true;
846 }
847
848 static int
849 populate_dump_types(char *types_list, struct dump_types *dump_types,
850 struct dpctl_params *dpctl_p)
851 {
852 if (!types_list) {
853 enable_all_dump_types(dump_types);
854 return 0;
855 }
856
857 char *current_type;
858
859 while (types_list && types_list[0] != '\0') {
860 current_type = types_list;
861 size_t type_len = strcspn(current_type, ",");
862
863 types_list += type_len + (types_list[type_len] != '\0');
864 current_type[type_len] = '\0';
865
866 if (!strcmp(current_type, "ovs")) {
867 dump_types->ovs = true;
868 } else if (!strcmp(current_type, "tc")) {
869 dump_types->tc = true;
870 } else if (!strcmp(current_type, "offloaded")) {
871 dump_types->offloaded = true;
872 } else if (!strcmp(current_type, "non-offloaded")) {
873 dump_types->non_offloaded = true;
874 } else if (!strcmp(current_type, "all")) {
875 enable_all_dump_types(dump_types);
876 } else {
877 dpctl_error(dpctl_p, EINVAL, "Failed to parse type (%s)",
878 current_type);
879 return EINVAL;
880 }
881 }
882 return 0;
883 }
884
885 static void
886 determine_dpif_flow_dump_types(struct dump_types *dump_types,
887 struct dpif_flow_dump_types *dpif_dump_types)
888 {
889 dpif_dump_types->ovs_flows = dump_types->ovs || dump_types->non_offloaded;
890 dpif_dump_types->netdev_flows = dump_types->tc || dump_types->offloaded
891 || dump_types->non_offloaded;
892 }
893
894 static bool
895 flow_passes_type_filter(const struct dpif_flow *f,
896 struct dump_types *dump_types)
897 {
898 if (dump_types->ovs && !strcmp(f->attrs.dp_layer, "ovs")) {
899 return true;
900 }
901 if (dump_types->tc && !strcmp(f->attrs.dp_layer, "tc")) {
902 return true;
903 }
904 if (dump_types->offloaded && f->attrs.offloaded) {
905 return true;
906 }
907 if (dump_types->non_offloaded && !(f->attrs.offloaded)) {
908 return true;
909 }
910 return false;
911 }
912
913 static struct hmap *
914 dpctl_get_portno_names(struct dpif *dpif, const struct dpctl_params *dpctl_p)
915 {
916 if (dpctl_p->names) {
917 struct hmap *portno_names = xmalloc(sizeof *portno_names);
918 hmap_init(portno_names);
919
920 struct dpif_port_dump port_dump;
921 struct dpif_port dpif_port;
922 DPIF_PORT_FOR_EACH (&dpif_port, &port_dump, dpif) {
923 odp_portno_names_set(portno_names, dpif_port.port_no,
924 dpif_port.name);
925 }
926
927 return portno_names;
928 } else {
929 return NULL;
930 }
931 }
932
933 static void
934 dpctl_free_portno_names(struct hmap *portno_names)
935 {
936 if (portno_names) {
937 odp_portno_names_destroy(portno_names);
938 hmap_destroy(portno_names);
939 free(portno_names);
940 }
941 }
942
943 static int
944 dpctl_dump_flows(int argc, const char *argv[], struct dpctl_params *dpctl_p)
945 {
946 struct dpif *dpif;
947 struct ds ds;
948
949 char *filter = NULL;
950 struct flow flow_filter;
951 struct flow_wildcards wc_filter;
952 char *types_list = NULL;
953 struct dump_types dump_types;
954 struct dpif_flow_dump_types dpif_dump_types;
955
956 struct dpif_flow_dump_thread *flow_dump_thread;
957 struct dpif_flow_dump *flow_dump;
958 struct dpif_flow f;
959 int pmd_id = PMD_ID_NULL;
960 int lastargc = 0;
961 int error;
962
963 while (argc > 1 && lastargc != argc) {
964 lastargc = argc;
965 if (!strncmp(argv[argc - 1], "filter=", 7) && !filter) {
966 filter = xstrdup(argv[--argc] + 7);
967 } else if (!strncmp(argv[argc - 1], "type=", 5) && !types_list) {
968 types_list = xstrdup(argv[--argc] + 5);
969 }
970 }
971
972 error = opt_dpif_open(argc, argv, dpctl_p, 2, &dpif);
973 if (error) {
974 goto out_free;
975 }
976
977 struct hmap *portno_names = dpctl_get_portno_names(dpif, dpctl_p);
978
979 if (filter) {
980 struct ofputil_port_map port_map;
981 ofputil_port_map_init(&port_map);
982
983 struct dpif_port_dump port_dump;
984 struct dpif_port dpif_port;
985 DPIF_PORT_FOR_EACH (&dpif_port, &port_dump, dpif) {
986 ofputil_port_map_put(&port_map,
987 u16_to_ofp(odp_to_u32(dpif_port.port_no)),
988 dpif_port.name);
989 }
990 char *err = parse_ofp_exact_flow(&flow_filter, &wc_filter, NULL,
991 filter, &port_map);
992 ofputil_port_map_destroy(&port_map);
993 if (err) {
994 dpctl_error(dpctl_p, 0, "Failed to parse filter (%s)", err);
995 free(err);
996 error = EINVAL;
997 goto out_dpifclose;
998 }
999 }
1000
1001 memset(&dump_types, 0, sizeof dump_types);
1002 error = populate_dump_types(types_list, &dump_types, dpctl_p);
1003 if (error) {
1004 goto out_free;
1005 }
1006 determine_dpif_flow_dump_types(&dump_types, &dpif_dump_types);
1007
1008 /* Make sure that these values are different. PMD_ID_NULL means that the
1009 * pmd is unspecified (e.g. because the datapath doesn't have different
1010 * pmd threads), while NON_PMD_CORE_ID refers to every non pmd threads
1011 * in the userspace datapath */
1012 BUILD_ASSERT(PMD_ID_NULL != NON_PMD_CORE_ID);
1013
1014 ds_init(&ds);
1015 memset(&f, 0, sizeof f);
1016 flow_dump = dpif_flow_dump_create(dpif, false, &dpif_dump_types);
1017 flow_dump_thread = dpif_flow_dump_thread_create(flow_dump);
1018 while (dpif_flow_dump_next(flow_dump_thread, &f, 1)) {
1019 if (filter) {
1020 struct flow flow;
1021 struct flow_wildcards wc;
1022 struct match match, match_filter;
1023 struct minimatch minimatch;
1024
1025 odp_flow_key_to_flow(f.key, f.key_len, &flow, NULL);
1026 odp_flow_key_to_mask(f.mask, f.mask_len, &wc, &flow, NULL);
1027 match_init(&match, &flow, &wc);
1028
1029 match_init(&match_filter, &flow_filter, &wc);
1030 match_init(&match_filter, &match_filter.flow, &wc_filter);
1031 minimatch_init(&minimatch, &match_filter);
1032
1033 if (!minimatch_matches_flow(&minimatch, &match.flow)) {
1034 minimatch_destroy(&minimatch);
1035 continue;
1036 }
1037 minimatch_destroy(&minimatch);
1038 }
1039 ds_clear(&ds);
1040 /* If 'pmd_id' is specified, overlapping flows could be dumped from
1041 * different pmd threads. So, separates dumps from different pmds
1042 * by printing a title line. */
1043 if (pmd_id != f.pmd_id) {
1044 if (f.pmd_id == NON_PMD_CORE_ID) {
1045 ds_put_format(&ds, "flow-dump from non-dpdk interfaces:\n");
1046 } else {
1047 ds_put_format(&ds, "flow-dump from pmd on cpu core: %d\n",
1048 f.pmd_id);
1049 }
1050 pmd_id = f.pmd_id;
1051 }
1052 if (flow_passes_type_filter(&f, &dump_types)) {
1053 format_dpif_flow(&ds, &f, portno_names, dpctl_p);
1054 dpctl_print(dpctl_p, "%s\n", ds_cstr(&ds));
1055 }
1056 }
1057 dpif_flow_dump_thread_destroy(flow_dump_thread);
1058 error = dpif_flow_dump_destroy(flow_dump);
1059
1060 if (error) {
1061 dpctl_error(dpctl_p, error, "Failed to dump flows from datapath");
1062 }
1063 ds_destroy(&ds);
1064
1065 out_dpifclose:
1066 dpctl_free_portno_names(portno_names);
1067 dpif_close(dpif);
1068 out_free:
1069 free(filter);
1070 free(types_list);
1071 return error;
1072 }
1073
1074 static int
1075 dpctl_put_flow(int argc, const char *argv[], enum dpif_flow_put_flags flags,
1076 struct dpctl_params *dpctl_p)
1077 {
1078 const char *key_s = argv[argc - 2];
1079 const char *actions_s = argv[argc - 1];
1080 struct dpif_flow_stats stats;
1081 struct dpif_port dpif_port;
1082 struct dpif_port_dump port_dump;
1083 struct ofpbuf actions;
1084 struct ofpbuf key;
1085 struct ofpbuf mask;
1086 struct dpif *dpif;
1087 ovs_u128 ufid;
1088 bool ufid_present;
1089 struct simap port_names;
1090 int n, error;
1091
1092 error = opt_dpif_open(argc, argv, dpctl_p, 4, &dpif);
1093 if (error) {
1094 return error;
1095 }
1096
1097 ufid_present = false;
1098 n = odp_ufid_from_string(key_s, &ufid);
1099 if (n < 0) {
1100 dpctl_error(dpctl_p, -n, "parsing flow ufid");
1101 return -n;
1102 } else if (n) {
1103 key_s += n;
1104 ufid_present = true;
1105 }
1106
1107 simap_init(&port_names);
1108 DPIF_PORT_FOR_EACH (&dpif_port, &port_dump, dpif) {
1109 simap_put(&port_names, dpif_port.name, odp_to_u32(dpif_port.port_no));
1110 }
1111
1112 ofpbuf_init(&key, 0);
1113 ofpbuf_init(&mask, 0);
1114 char *error_s;
1115 error = odp_flow_from_string(key_s, &port_names, &key, &mask, &error_s);
1116 simap_destroy(&port_names);
1117 if (error) {
1118 dpctl_error(dpctl_p, error, "parsing flow key (%s)", error_s);
1119 free(error_s);
1120 goto out_freekeymask;
1121 }
1122
1123 ofpbuf_init(&actions, 0);
1124 error = odp_actions_from_string(actions_s, NULL, &actions);
1125 if (error) {
1126 dpctl_error(dpctl_p, error, "parsing actions");
1127 goto out_freeactions;
1128 }
1129
1130 /* The flow will be added on all pmds currently in the datapath. */
1131 error = dpif_flow_put(dpif, flags,
1132 key.data, key.size,
1133 mask.size == 0 ? NULL : mask.data,
1134 mask.size, actions.data,
1135 actions.size, ufid_present ? &ufid : NULL,
1136 PMD_ID_NULL,
1137 dpctl_p->print_statistics ? &stats : NULL);
1138
1139 if (error) {
1140 dpctl_error(dpctl_p, error, "updating flow table");
1141 goto out_freeactions;
1142 }
1143
1144 if (dpctl_p->print_statistics) {
1145 struct ds s;
1146
1147 ds_init(&s);
1148 dpif_flow_stats_format(&stats, &s);
1149 dpctl_print(dpctl_p, "%s\n", ds_cstr(&s));
1150 ds_destroy(&s);
1151 }
1152
1153 out_freeactions:
1154 ofpbuf_uninit(&actions);
1155 out_freekeymask:
1156 ofpbuf_uninit(&mask);
1157 ofpbuf_uninit(&key);
1158 dpif_close(dpif);
1159 return error;
1160 }
1161
1162 static int
1163 dpctl_add_flow(int argc, const char *argv[], struct dpctl_params *dpctl_p)
1164 {
1165 return dpctl_put_flow(argc, argv, DPIF_FP_CREATE, dpctl_p);
1166 }
1167
1168 static int
1169 dpctl_mod_flow(int argc, const char *argv[], struct dpctl_params *dpctl_p)
1170 {
1171 enum dpif_flow_put_flags flags;
1172
1173 flags = DPIF_FP_MODIFY;
1174 if (dpctl_p->may_create) {
1175 flags |= DPIF_FP_CREATE;
1176 }
1177 if (dpctl_p->zero_statistics) {
1178 flags |= DPIF_FP_ZERO_STATS;
1179 }
1180
1181 return dpctl_put_flow(argc, argv, flags, dpctl_p);
1182 }
1183
1184 static int
1185 dpctl_get_flow(int argc, const char *argv[], struct dpctl_params *dpctl_p)
1186 {
1187 const char *key_s = argv[argc - 1];
1188 struct dpif_flow flow;
1189 struct dpif *dpif;
1190 ovs_u128 ufid;
1191 struct ofpbuf buf;
1192 uint64_t stub[DPIF_FLOW_BUFSIZE / 8];
1193 struct ds ds;
1194 int n, error;
1195
1196 error = opt_dpif_open(argc, argv, dpctl_p, 3, &dpif);
1197 if (error) {
1198 return error;
1199 }
1200
1201 ofpbuf_use_stub(&buf, &stub, sizeof stub);
1202
1203 struct hmap *portno_names = dpctl_get_portno_names(dpif, dpctl_p);
1204
1205 n = odp_ufid_from_string(key_s, &ufid);
1206 if (n <= 0) {
1207 dpctl_error(dpctl_p, -n, "parsing flow ufid");
1208 goto out;
1209 }
1210
1211 /* In case of PMD will be returned flow from first PMD thread with match. */
1212 error = dpif_flow_get(dpif, NULL, 0, &ufid, PMD_ID_NULL, &buf, &flow);
1213 if (error) {
1214 dpctl_error(dpctl_p, error, "getting flow");
1215 goto out;
1216 }
1217
1218 ds_init(&ds);
1219 format_dpif_flow(&ds, &flow, portno_names, dpctl_p);
1220 dpctl_print(dpctl_p, "%s\n", ds_cstr(&ds));
1221 ds_destroy(&ds);
1222
1223 out:
1224 dpctl_free_portno_names(portno_names);
1225 ofpbuf_uninit(&buf);
1226 dpif_close(dpif);
1227 return error;
1228 }
1229
1230 static int
1231 dpctl_del_flow(int argc, const char *argv[], struct dpctl_params *dpctl_p)
1232 {
1233 const char *key_s = argv[argc - 1];
1234 struct dpif_flow_stats stats;
1235 struct dpif_port dpif_port;
1236 struct dpif_port_dump port_dump;
1237 struct ofpbuf key;
1238 struct ofpbuf mask; /* To be ignored. */
1239 struct dpif *dpif;
1240 ovs_u128 ufid;
1241 bool ufid_present;
1242 struct simap port_names;
1243 int n, error;
1244
1245 error = opt_dpif_open(argc, argv, dpctl_p, 3, &dpif);
1246 if (error) {
1247 return error;
1248 }
1249
1250 ufid_present = false;
1251 n = odp_ufid_from_string(key_s, &ufid);
1252 if (n < 0) {
1253 dpctl_error(dpctl_p, -n, "parsing flow ufid");
1254 return -n;
1255 } else if (n) {
1256 key_s += n;
1257 ufid_present = true;
1258 }
1259
1260 simap_init(&port_names);
1261 DPIF_PORT_FOR_EACH (&dpif_port, &port_dump, dpif) {
1262 simap_put(&port_names, dpif_port.name, odp_to_u32(dpif_port.port_no));
1263 }
1264
1265 ofpbuf_init(&key, 0);
1266 ofpbuf_init(&mask, 0);
1267
1268 char *error_s;
1269 error = odp_flow_from_string(key_s, &port_names, &key, &mask, &error_s);
1270 if (error) {
1271 dpctl_error(dpctl_p, error, "%s", error_s);
1272 free(error_s);
1273 goto out;
1274 }
1275
1276 /* The flow will be deleted from all pmds currently in the datapath. */
1277 error = dpif_flow_del(dpif, key.data, key.size,
1278 ufid_present ? &ufid : NULL, PMD_ID_NULL,
1279 dpctl_p->print_statistics ? &stats : NULL);
1280
1281 if (error) {
1282 dpctl_error(dpctl_p, error, "deleting flow");
1283 if (error == ENOENT && !ufid_present) {
1284 struct ds s;
1285
1286 ds_init(&s);
1287 ds_put_format(&s, "Perhaps you need to specify a UFID?");
1288 dpctl_print(dpctl_p, "%s\n", ds_cstr(&s));
1289 ds_destroy(&s);
1290 }
1291 goto out;
1292 }
1293
1294 if (dpctl_p->print_statistics) {
1295 struct ds s;
1296
1297 ds_init(&s);
1298 dpif_flow_stats_format(&stats, &s);
1299 dpctl_print(dpctl_p, "%s\n", ds_cstr(&s));
1300 ds_destroy(&s);
1301 }
1302
1303 out:
1304 ofpbuf_uninit(&mask);
1305 ofpbuf_uninit(&key);
1306 simap_destroy(&port_names);
1307 dpif_close(dpif);
1308 return error;
1309 }
1310
1311 static int
1312 dpctl_del_flows(int argc, const char *argv[], struct dpctl_params *dpctl_p)
1313 {
1314 struct dpif *dpif;
1315
1316 int error = opt_dpif_open(argc, argv, dpctl_p, 2, &dpif);
1317 if (error) {
1318 return error;
1319 }
1320
1321 error = dpif_flow_flush(dpif);
1322 if (error) {
1323 dpctl_error(dpctl_p, error, "deleting all flows");
1324 }
1325 dpif_close(dpif);
1326 return error;
1327 }
1328
1329 static int
1330 dpctl_help(int argc OVS_UNUSED, const char *argv[] OVS_UNUSED,
1331 struct dpctl_params *dpctl_p)
1332 {
1333 if (dpctl_p->usage) {
1334 dpctl_p->usage(dpctl_p->aux);
1335 }
1336
1337 return 0;
1338 }
1339
1340 static int
1341 dpctl_list_commands(int argc OVS_UNUSED, const char *argv[] OVS_UNUSED,
1342 struct dpctl_params *dpctl_p)
1343 {
1344 struct ds ds = DS_EMPTY_INITIALIZER;
1345 const struct dpctl_command *commands = get_all_dpctl_commands();
1346
1347 ds_put_cstr(&ds, "The available commands are:\n");
1348 for (; commands->name; commands++) {
1349 const struct dpctl_command *c = commands;
1350
1351 ds_put_format(&ds, " %s%-23s %s\n", dpctl_p->is_appctl ? "dpctl/" : "",
1352 c->name, c->usage);
1353 }
1354 dpctl_puts(dpctl_p, false, ds.string);
1355 ds_destroy(&ds);
1356
1357 return 0;
1358 }
1359 \f
1360
1361 static int
1362 dpctl_dump_conntrack(int argc, const char *argv[],
1363 struct dpctl_params *dpctl_p)
1364 {
1365 struct ct_dpif_dump_state *dump;
1366 struct ct_dpif_entry cte;
1367 uint16_t zone, *pzone = NULL;
1368 int tot_bkts;
1369 struct dpif *dpif;
1370 int error;
1371
1372 if (argc > 1 && ovs_scan(argv[argc - 1], "zone=%"SCNu16, &zone)) {
1373 pzone = &zone;
1374 argc--;
1375 }
1376
1377 error = opt_dpif_open(argc, argv, dpctl_p, 2, &dpif);
1378 if (error) {
1379 return error;
1380 }
1381
1382 error = ct_dpif_dump_start(dpif, &dump, pzone, &tot_bkts);
1383 if (error) {
1384 dpctl_error(dpctl_p, error, "starting conntrack dump");
1385 dpif_close(dpif);
1386 return error;
1387 }
1388
1389 while (!(error = ct_dpif_dump_next(dump, &cte))) {
1390 struct ds s = DS_EMPTY_INITIALIZER;
1391
1392 ct_dpif_format_entry(&cte, &s, dpctl_p->verbosity,
1393 dpctl_p->print_statistics);
1394 ct_dpif_entry_uninit(&cte);
1395
1396 dpctl_print(dpctl_p, "%s\n", ds_cstr(&s));
1397 ds_destroy(&s);
1398 }
1399 if (error == EOF) {
1400 /* Any CT entry was dumped with no issue. */
1401 error = 0;
1402 } else if (error) {
1403 dpctl_error(dpctl_p, error, "dumping conntrack entry");
1404 }
1405
1406 ct_dpif_dump_done(dump);
1407 dpif_close(dpif);
1408 return error;
1409 }
1410
1411 static int
1412 dpctl_flush_conntrack(int argc, const char *argv[],
1413 struct dpctl_params *dpctl_p)
1414 {
1415 struct dpif *dpif = NULL;
1416 struct ct_dpif_tuple tuple, *ptuple = NULL;
1417 struct ds ds = DS_EMPTY_INITIALIZER;
1418 uint16_t zone, *pzone = NULL;
1419 int error;
1420 int args = argc - 1;
1421
1422 /* Parse ct tuple */
1423 if (args && ct_dpif_parse_tuple(&tuple, argv[args], &ds)) {
1424 ptuple = &tuple;
1425 args--;
1426 }
1427
1428 /* Parse zone */
1429 if (args && ovs_scan(argv[args], "zone=%"SCNu16, &zone)) {
1430 pzone = &zone;
1431 args--;
1432 }
1433
1434 /* Report error if there are more than one unparsed argument. */
1435 if (args > 1) {
1436 ds_put_cstr(&ds, "invalid arguments");
1437 error = EINVAL;
1438 goto error;
1439 }
1440
1441 error = opt_dpif_open(argc, argv, dpctl_p, 4, &dpif);
1442 if (error) {
1443 return error;
1444 }
1445
1446 error = ct_dpif_flush(dpif, pzone, ptuple);
1447 if (!error) {
1448 dpif_close(dpif);
1449 return 0;
1450 } else {
1451 ds_put_cstr(&ds, "failed to flush conntrack");
1452 }
1453
1454 error:
1455 dpctl_error(dpctl_p, error, "%s", ds_cstr(&ds));
1456 ds_destroy(&ds);
1457 dpif_close(dpif);
1458 return error;
1459 }
1460
1461 static int
1462 dpctl_ct_stats_show(int argc, const char *argv[],
1463 struct dpctl_params *dpctl_p)
1464 {
1465 struct dpif *dpif;
1466 struct ct_dpif_dump_state *dump;
1467 struct ct_dpif_entry cte;
1468 uint16_t zone, *pzone = NULL;
1469 int tot_bkts;
1470 int lastargc = 0;
1471
1472 int proto_stats[CT_STATS_MAX];
1473 int tcp_conn_per_states[CT_DPIF_TCPS_MAX_NUM];
1474 int error;
1475
1476 bool verbose = dpctl_p->verbosity;
1477
1478 while (argc > 1 && lastargc != argc) {
1479 lastargc = argc;
1480 if (!strncmp(argv[argc - 1], "verbose", 7)) {
1481 /* Support "verbose" argument for backwards compatibility. */
1482 verbose = true;
1483 argc--;
1484 } else if (!strncmp(argv[argc - 1], "zone=", 5)) {
1485 if (ovs_scan(argv[argc - 1], "zone=%"SCNu16, &zone)) {
1486 pzone = &zone;
1487 argc--;
1488 }
1489 }
1490 }
1491
1492 error = opt_dpif_open(argc, argv, dpctl_p, 2, &dpif);
1493 if (error) {
1494 return error;
1495 }
1496
1497 memset(proto_stats, 0, sizeof(proto_stats));
1498 memset(tcp_conn_per_states, 0, sizeof(tcp_conn_per_states));
1499 error = ct_dpif_dump_start(dpif, &dump, pzone, &tot_bkts);
1500 if (error) {
1501 dpctl_error(dpctl_p, error, "starting conntrack dump");
1502 dpif_close(dpif);
1503 return error;
1504 }
1505
1506 int tot_conn = 0;
1507 while (!(error = ct_dpif_dump_next(dump, &cte))) {
1508 ct_dpif_entry_uninit(&cte);
1509 tot_conn++;
1510 switch (cte.tuple_orig.ip_proto) {
1511 case IPPROTO_ICMP:
1512 proto_stats[CT_STATS_ICMP]++;
1513 break;
1514 case IPPROTO_ICMPV6:
1515 proto_stats[CT_STATS_ICMPV6]++;
1516 break;
1517 case IPPROTO_TCP:
1518 proto_stats[CT_STATS_TCP]++;
1519 uint8_t tcp_state;
1520 /* We keep two separate tcp states, but we print just one. The
1521 * Linux kernel connection tracker internally keeps only one state,
1522 * so 'state_orig' and 'state_reply', will be the same. */
1523 tcp_state = MAX(cte.protoinfo.tcp.state_orig,
1524 cte.protoinfo.tcp.state_reply);
1525 tcp_state = ct_dpif_coalesce_tcp_state(tcp_state);
1526 tcp_conn_per_states[tcp_state]++;
1527 break;
1528 case IPPROTO_UDP:
1529 proto_stats[CT_STATS_UDP]++;
1530 break;
1531 case IPPROTO_SCTP:
1532 proto_stats[CT_STATS_SCTP]++;
1533 break;
1534 case IPPROTO_UDPLITE:
1535 proto_stats[CT_STATS_UDPLITE]++;
1536 break;
1537 case IPPROTO_DCCP:
1538 proto_stats[CT_STATS_DCCP]++;
1539 break;
1540 case IPPROTO_IGMP:
1541 proto_stats[CT_STATS_IGMP]++;
1542 break;
1543 default:
1544 proto_stats[CT_STATS_OTHER]++;
1545 break;
1546 }
1547 }
1548 if (error == EOF) {
1549 /* All CT entries were dumped with no issue. */
1550 error = 0;
1551 } else if (error) {
1552 dpctl_error(dpctl_p, error, "dumping conntrack entry");
1553 /* Fall through to show any other info we collected. */
1554 }
1555
1556 dpctl_print(dpctl_p, "Connections Stats:\n Total: %d\n", tot_conn);
1557 if (proto_stats[CT_STATS_TCP]) {
1558 dpctl_print(dpctl_p, " TCP: %d\n", proto_stats[CT_STATS_TCP]);
1559 if (verbose) {
1560 dpctl_print(dpctl_p, " Conn per TCP states:\n");
1561 for (int i = 0; i < CT_DPIF_TCPS_MAX_NUM; i++) {
1562 if (tcp_conn_per_states[i]) {
1563 struct ds s = DS_EMPTY_INITIALIZER;
1564 ct_dpif_format_tcp_stat(&s, i, tcp_conn_per_states[i]);
1565 dpctl_print(dpctl_p, "%s\n", ds_cstr(&s));
1566 ds_destroy(&s);
1567 }
1568 }
1569 }
1570 }
1571 if (proto_stats[CT_STATS_UDP]) {
1572 dpctl_print(dpctl_p, " UDP: %d\n", proto_stats[CT_STATS_UDP]);
1573 }
1574 if (proto_stats[CT_STATS_UDPLITE]) {
1575 dpctl_print(dpctl_p, " UDPLITE: %d\n", proto_stats[CT_STATS_UDPLITE]);
1576 }
1577 if (proto_stats[CT_STATS_SCTP]) {
1578 dpctl_print(dpctl_p, " SCTP: %d\n", proto_stats[CT_STATS_SCTP]);
1579 }
1580 if (proto_stats[CT_STATS_ICMP]) {
1581 dpctl_print(dpctl_p, " ICMP: %d\n", proto_stats[CT_STATS_ICMP]);
1582 }
1583 if (proto_stats[CT_STATS_DCCP]) {
1584 dpctl_print(dpctl_p, " DCCP: %d\n", proto_stats[CT_STATS_DCCP]);
1585 }
1586 if (proto_stats[CT_STATS_IGMP]) {
1587 dpctl_print(dpctl_p, " IGMP: %d\n", proto_stats[CT_STATS_IGMP]);
1588 }
1589 if (proto_stats[CT_STATS_OTHER]) {
1590 dpctl_print(dpctl_p, " Other: %d\n", proto_stats[CT_STATS_OTHER]);
1591 }
1592
1593 ct_dpif_dump_done(dump);
1594 dpif_close(dpif);
1595 return error;
1596 }
1597
1598 #define CT_BKTS_GT "gt="
1599 static int
1600 dpctl_ct_bkts(int argc, const char *argv[],
1601 struct dpctl_params *dpctl_p)
1602 {
1603 struct dpif *dpif;
1604 struct ct_dpif_dump_state *dump;
1605 struct ct_dpif_entry cte;
1606 uint16_t gt = 0; /* Threshold: display value when greater than gt. */
1607 uint16_t *pzone = NULL;
1608 int tot_bkts = 0;
1609 int error;
1610
1611 if (argc > 1 && !strncmp(argv[argc - 1], CT_BKTS_GT, strlen(CT_BKTS_GT))) {
1612 if (ovs_scan(argv[argc - 1], CT_BKTS_GT"%"SCNu16, &gt)) {
1613 argc--;
1614 }
1615 }
1616
1617 error = opt_dpif_open(argc, argv, dpctl_p, 2, &dpif);
1618 if (error) {
1619 return error;
1620 }
1621
1622 error = ct_dpif_dump_start(dpif, &dump, pzone, &tot_bkts);
1623 if (error) {
1624 dpctl_error(dpctl_p, error, "starting conntrack dump");
1625 dpif_close(dpif);
1626 return error;
1627 }
1628 if (tot_bkts == -1) {
1629 /* Command not available when called by kernel OvS. */
1630 dpctl_print(dpctl_p,
1631 "Command is available for UserSpace ConnTracker only.\n");
1632 ct_dpif_dump_done(dump);
1633 dpif_close(dpif);
1634 return 0;
1635 }
1636
1637 dpctl_print(dpctl_p, "Total Buckets: %d\n", tot_bkts);
1638
1639 int tot_conn = 0;
1640 uint32_t *conn_per_bkts = xzalloc(tot_bkts * sizeof(uint32_t));
1641
1642 while (!(error = ct_dpif_dump_next(dump, &cte))) {
1643 ct_dpif_entry_uninit(&cte);
1644 tot_conn++;
1645 if (tot_bkts > 0) {
1646 if (cte.bkt < tot_bkts) {
1647 conn_per_bkts[cte.bkt]++;
1648 } else {
1649 dpctl_print(dpctl_p, "Bucket nr out of range: %d >= %d\n",
1650 cte.bkt, tot_bkts);
1651 }
1652 }
1653 }
1654 if (error == EOF) {
1655 /* All CT entries were dumped with no issue. */
1656 error = 0;
1657 } else if (error) {
1658 dpctl_error(dpctl_p, error, "dumping conntrack entry");
1659 /* Fall through and display all the collected info. */
1660 }
1661
1662 dpctl_print(dpctl_p, "Current Connections: %d\n", tot_conn);
1663 dpctl_print(dpctl_p, "\n");
1664 if (tot_bkts && tot_conn) {
1665 dpctl_print(dpctl_p, "+-----------+"
1666 "-----------------------------------------+\n");
1667 dpctl_print(dpctl_p, "| Buckets |"
1668 " Connections per Buckets |\n");
1669 dpctl_print(dpctl_p, "+-----------+"
1670 "-----------------------------------------+");
1671 #define NUM_BKTS_DIPLAYED_PER_ROW 8
1672 for (int i = 0; i < tot_bkts; i++) {
1673 if (i % NUM_BKTS_DIPLAYED_PER_ROW == 0) {
1674 dpctl_print(dpctl_p, "\n %3d..%3d | ",
1675 i, i + NUM_BKTS_DIPLAYED_PER_ROW - 1);
1676 }
1677 if (conn_per_bkts[i] > gt) {
1678 dpctl_print(dpctl_p, "%5d", conn_per_bkts[i]);
1679 } else {
1680 dpctl_print(dpctl_p, "%5s", ".");
1681 }
1682 }
1683 dpctl_print(dpctl_p, "\n\n");
1684 }
1685
1686 ct_dpif_dump_done(dump);
1687 dpif_close(dpif);
1688 free(conn_per_bkts);
1689 return error;
1690 }
1691 \f
1692 static int
1693 dpctl_ct_set_maxconns(int argc, const char *argv[],
1694 struct dpctl_params *dpctl_p)
1695 {
1696 struct dpif *dpif;
1697 int error = opt_dpif_open(argc, argv, dpctl_p, 3, &dpif);
1698 if (!error) {
1699 uint32_t maxconns;
1700 if (ovs_scan(argv[argc - 1], "%"SCNu32, &maxconns)) {
1701 error = ct_dpif_set_maxconns(dpif, maxconns);
1702
1703 if (!error) {
1704 dpctl_print(dpctl_p, "setting maxconns successful");
1705 } else {
1706 dpctl_error(dpctl_p, error, "ct set maxconns failed");
1707 }
1708 } else {
1709 error = EINVAL;
1710 dpctl_error(dpctl_p, error, "maxconns missing or malformed");
1711 }
1712 dpif_close(dpif);
1713 }
1714
1715 return error;
1716 }
1717
1718 static int
1719 dpctl_ct_get_maxconns(int argc, const char *argv[],
1720 struct dpctl_params *dpctl_p)
1721 {
1722 struct dpif *dpif;
1723 int error = opt_dpif_open(argc, argv, dpctl_p, 2, &dpif);
1724 if (!error) {
1725 uint32_t maxconns;
1726 error = ct_dpif_get_maxconns(dpif, &maxconns);
1727
1728 if (!error) {
1729 dpctl_print(dpctl_p, "%u\n", maxconns);
1730 } else {
1731 dpctl_error(dpctl_p, error, "maxconns could not be retrieved");
1732 }
1733 dpif_close(dpif);
1734 }
1735
1736 return error;
1737 }
1738
1739 static int
1740 dpctl_ct_get_nconns(int argc, const char *argv[],
1741 struct dpctl_params *dpctl_p)
1742 {
1743 struct dpif *dpif;
1744 int error = opt_dpif_open(argc, argv, dpctl_p, 2, &dpif);
1745 if (!error) {
1746 uint32_t nconns;
1747 error = ct_dpif_get_nconns(dpif, &nconns);
1748
1749 if (!error) {
1750 dpctl_print(dpctl_p, "%u\n", nconns);
1751 } else {
1752 dpctl_error(dpctl_p, error, "nconns could not be retrieved");
1753 }
1754 dpif_close(dpif);
1755 }
1756
1757 return error;
1758 }
1759
1760 static int
1761 dpctl_ct_set_limits(int argc, const char *argv[],
1762 struct dpctl_params *dpctl_p)
1763 {
1764 struct dpif *dpif;
1765 struct ds ds = DS_EMPTY_INITIALIZER;
1766 int i = dp_arg_exists(argc, argv) ? 2 : 1;
1767 uint32_t default_limit, *p_default_limit = NULL;
1768 struct ovs_list zone_limits = OVS_LIST_INITIALIZER(&zone_limits);
1769
1770 int error = opt_dpif_open(argc, argv, dpctl_p, INT_MAX, &dpif);
1771 if (error) {
1772 return error;
1773 }
1774
1775 /* Parse default limit */
1776 if (!strncmp(argv[i], "default=", 8)) {
1777 if (ovs_scan(argv[i], "default=%"SCNu32, &default_limit)) {
1778 p_default_limit = &default_limit;
1779 i++;
1780 } else {
1781 ds_put_cstr(&ds, "invalid default limit");
1782 error = EINVAL;
1783 goto error;
1784 }
1785 }
1786
1787 /* Parse ct zone limit tuples */
1788 while (i < argc) {
1789 uint16_t zone;
1790 uint32_t limit;
1791 if (!ct_dpif_parse_zone_limit_tuple(argv[i++], &zone, &limit, &ds)) {
1792 error = EINVAL;
1793 goto error;
1794 }
1795 ct_dpif_push_zone_limit(&zone_limits, zone, limit, 0);
1796 }
1797
1798 error = ct_dpif_set_limits(dpif, p_default_limit, &zone_limits);
1799 if (!error) {
1800 ct_dpif_free_zone_limits(&zone_limits);
1801 dpif_close(dpif);
1802 return 0;
1803 } else {
1804 ds_put_cstr(&ds, "failed to set conntrack limit");
1805 }
1806
1807 error:
1808 dpctl_error(dpctl_p, error, "%s", ds_cstr(&ds));
1809 ds_destroy(&ds);
1810 ct_dpif_free_zone_limits(&zone_limits);
1811 dpif_close(dpif);
1812 return error;
1813 }
1814
1815 static int
1816 parse_ct_limit_zones(const char *argv, struct ovs_list *zone_limits,
1817 struct ds *ds)
1818 {
1819 char *save_ptr = NULL, *argcopy, *next_zone;
1820 uint16_t zone;
1821
1822 if (strncmp(argv, "zone=", 5)) {
1823 ds_put_format(ds, "invalid argument %s", argv);
1824 return EINVAL;
1825 }
1826
1827 argcopy = xstrdup(argv + 5);
1828 next_zone = strtok_r(argcopy, ",", &save_ptr);
1829
1830 do {
1831 if (ovs_scan(next_zone, "%"SCNu16, &zone)) {
1832 ct_dpif_push_zone_limit(zone_limits, zone, 0, 0);
1833 } else {
1834 ds_put_cstr(ds, "invalid zone");
1835 free(argcopy);
1836 return EINVAL;
1837 }
1838 } while ((next_zone = strtok_r(NULL, ",", &save_ptr)) != NULL);
1839
1840 free(argcopy);
1841 return 0;
1842 }
1843
1844 static int
1845 dpctl_ct_del_limits(int argc, const char *argv[],
1846 struct dpctl_params *dpctl_p)
1847 {
1848 struct dpif *dpif;
1849 struct ds ds = DS_EMPTY_INITIALIZER;
1850 int error;
1851 int i = dp_arg_exists(argc, argv) ? 2 : 1;
1852 struct ovs_list zone_limits = OVS_LIST_INITIALIZER(&zone_limits);
1853
1854 error = opt_dpif_open(argc, argv, dpctl_p, 3, &dpif);
1855 if (error) {
1856 return error;
1857 }
1858
1859 error = parse_ct_limit_zones(argv[i], &zone_limits, &ds);
1860 if (error) {
1861 goto error;
1862 }
1863
1864 error = ct_dpif_del_limits(dpif, &zone_limits);
1865 if (!error) {
1866 goto out;
1867 } else {
1868 ds_put_cstr(&ds, "failed to delete conntrack limit");
1869 }
1870
1871 error:
1872 dpctl_error(dpctl_p, error, "%s", ds_cstr(&ds));
1873 ds_destroy(&ds);
1874 out:
1875 ct_dpif_free_zone_limits(&zone_limits);
1876 dpif_close(dpif);
1877 return error;
1878 }
1879
1880 static int
1881 dpctl_ct_get_limits(int argc, const char *argv[],
1882 struct dpctl_params *dpctl_p)
1883 {
1884 struct dpif *dpif;
1885 struct ds ds = DS_EMPTY_INITIALIZER;
1886 uint32_t default_limit;
1887 int i = dp_arg_exists(argc, argv) ? 2 : 1;
1888 struct ovs_list list_query = OVS_LIST_INITIALIZER(&list_query);
1889 struct ovs_list list_reply = OVS_LIST_INITIALIZER(&list_reply);
1890
1891 int error = opt_dpif_open(argc, argv, dpctl_p, 3, &dpif);
1892 if (error) {
1893 return error;
1894 }
1895
1896 if (argc > i) {
1897 error = parse_ct_limit_zones(argv[i], &list_query, &ds);
1898 if (error) {
1899 goto error;
1900 }
1901 }
1902
1903 error = ct_dpif_get_limits(dpif, &default_limit, &list_query,
1904 &list_reply);
1905 if (!error) {
1906 ct_dpif_format_zone_limits(default_limit, &list_reply, &ds);
1907 dpctl_print(dpctl_p, "%s\n", ds_cstr(&ds));
1908 goto out;
1909 } else {
1910 ds_put_format(&ds, "failed to get conntrack limit %s",
1911 ovs_strerror(error));
1912 }
1913
1914 error:
1915 dpctl_error(dpctl_p, error, "%s", ds_cstr(&ds));
1916 out:
1917 ds_destroy(&ds);
1918 ct_dpif_free_zone_limits(&list_query);
1919 ct_dpif_free_zone_limits(&list_reply);
1920 dpif_close(dpif);
1921 return error;
1922 }
1923
1924 static int
1925 ipf_set_enabled__(int argc, const char *argv[], struct dpctl_params *dpctl_p,
1926 bool enabled)
1927 {
1928 struct dpif *dpif;
1929 int error = opt_dpif_open(argc, argv, dpctl_p, 4, &dpif);
1930 if (!error) {
1931 char v4_or_v6[3] = {0};
1932 if (ovs_scan(argv[argc - 1], "%2s", v4_or_v6) &&
1933 (!strncmp(v4_or_v6, "v4", 2) || !strncmp(v4_or_v6, "v6", 2))) {
1934 error = ct_dpif_ipf_set_enabled(
1935 dpif, !strncmp(v4_or_v6, "v6", 2), enabled);
1936 if (!error) {
1937 dpctl_print(dpctl_p,
1938 "%s fragmentation reassembly successful",
1939 enabled ? "enabling" : "disabling");
1940 } else {
1941 dpctl_error(dpctl_p, error,
1942 "%s fragmentation reassembly failed",
1943 enabled ? "enabling" : "disabling");
1944 }
1945 } else {
1946 error = EINVAL;
1947 dpctl_error(dpctl_p, error,
1948 "parameter missing: 'v4' for IPv4 or 'v6' for IPv6");
1949 }
1950 dpif_close(dpif);
1951 }
1952 return error;
1953 }
1954
1955 static int
1956 dpctl_ipf_set_enabled(int argc, const char *argv[],
1957 struct dpctl_params *dpctl_p)
1958 {
1959 return ipf_set_enabled__(argc, argv, dpctl_p, true);
1960 }
1961
1962 static int
1963 dpctl_ipf_set_disabled(int argc, const char *argv[],
1964 struct dpctl_params *dpctl_p)
1965 {
1966 return ipf_set_enabled__(argc, argv, dpctl_p, false);
1967 }
1968
1969 static int
1970 dpctl_ipf_set_min_frag(int argc, const char *argv[],
1971 struct dpctl_params *dpctl_p)
1972 {
1973 struct dpif *dpif;
1974 int error = opt_dpif_open(argc, argv, dpctl_p, 4, &dpif);
1975 if (!error) {
1976 char v4_or_v6[3] = {0};
1977 if (ovs_scan(argv[argc - 2], "%2s", v4_or_v6) &&
1978 (!strncmp(v4_or_v6, "v4", 2) || !strncmp(v4_or_v6, "v6", 2))) {
1979 uint32_t min_fragment;
1980 if (ovs_scan(argv[argc - 1], "%"SCNu32, &min_fragment)) {
1981 error = ct_dpif_ipf_set_min_frag(
1982 dpif, !strncmp(v4_or_v6, "v6", 2), min_fragment);
1983 if (!error) {
1984 dpctl_print(dpctl_p,
1985 "setting minimum fragment size successful");
1986 } else {
1987 dpctl_error(dpctl_p, error,
1988 "requested minimum fragment size too small;"
1989 " see documentation");
1990 }
1991 } else {
1992 error = EINVAL;
1993 dpctl_error(dpctl_p, error,
1994 "parameter missing for minimum fragment size");
1995 }
1996 } else {
1997 error = EINVAL;
1998 dpctl_error(dpctl_p, error,
1999 "parameter missing: v4 for IPv4 or v6 for IPv6");
2000 }
2001 dpif_close(dpif);
2002 }
2003
2004 return error;
2005 }
2006
2007 static int
2008 dpctl_ipf_set_max_nfrags(int argc, const char *argv[],
2009 struct dpctl_params *dpctl_p)
2010 {
2011 struct dpif *dpif;
2012 int error = opt_dpif_open(argc, argv, dpctl_p, 3, &dpif);
2013 if (!error) {
2014 uint32_t nfrags_max;
2015 if (ovs_scan(argv[argc - 1], "%"SCNu32, &nfrags_max)) {
2016 error = ct_dpif_ipf_set_max_nfrags(dpif, nfrags_max);
2017 if (!error) {
2018 dpctl_print(dpctl_p,
2019 "setting maximum fragments successful");
2020 } else {
2021 dpctl_error(dpctl_p, error,
2022 "setting maximum fragments failed");
2023 }
2024 } else {
2025 error = EINVAL;
2026 dpctl_error(dpctl_p, error,
2027 "parameter missing for maximum fragments");
2028 }
2029 dpif_close(dpif);
2030 }
2031
2032 return error;
2033 }
2034
2035 static void
2036 dpctl_dump_ipf(struct dpif *dpif, struct dpctl_params *dpctl_p)
2037 {
2038 struct ipf_dump_ctx *dump_ctx;
2039 char *dump;
2040
2041 int error = ct_dpif_ipf_dump_start(dpif, &dump_ctx);
2042 if (error) {
2043 dpctl_error(dpctl_p, error, "starting ipf list dump");
2044 /* Nothing to clean up, just return. */
2045 return;
2046 }
2047
2048 dpctl_print(dpctl_p, "\n Fragment Lists:\n\n");
2049 while (!(error = ct_dpif_ipf_dump_next(dpif, dump_ctx, &dump))) {
2050 dpctl_print(dpctl_p, "%s\n", dump);
2051 free(dump);
2052 }
2053
2054 if (error && error != EOF) {
2055 dpctl_error(dpctl_p, error, "dumping ipf lists failed");
2056 }
2057
2058 ct_dpif_ipf_dump_done(dpif, dump_ctx);
2059 }
2060
2061 static int
2062 dpctl_ct_ipf_get_status(int argc, const char *argv[],
2063 struct dpctl_params *dpctl_p)
2064 {
2065 struct dpif *dpif;
2066 int error = opt_dpif_open(argc, argv, dpctl_p, 2, &dpif);
2067
2068 if (!error) {
2069 struct dpif_ipf_status dpif_ipf_status;
2070 error = ct_dpif_ipf_get_status(dpif, &dpif_ipf_status);
2071
2072 if (!error) {
2073 dpctl_print(dpctl_p, " Fragmentation Module Status\n");
2074 dpctl_print(dpctl_p, " ---------------------------\n");
2075 dpctl_print(dpctl_p, " v4 enabled: %u\n",
2076 dpif_ipf_status.v4.enabled);
2077 dpctl_print(dpctl_p, " v6 enabled: %u\n",
2078 dpif_ipf_status.v6.enabled);
2079 dpctl_print(dpctl_p, " max num frags (v4/v6): %u\n",
2080 dpif_ipf_status.nfrag_max);
2081 dpctl_print(dpctl_p, " num frag: %u\n",
2082 dpif_ipf_status.nfrag);
2083 dpctl_print(dpctl_p, " min v4 frag size: %u\n",
2084 dpif_ipf_status.v4.min_frag_size);
2085 dpctl_print(dpctl_p, " v4 frags accepted: %"PRIu64"\n",
2086 dpif_ipf_status.v4.nfrag_accepted);
2087 dpctl_print(dpctl_p, " v4 frags completed: %"PRIu64"\n",
2088 dpif_ipf_status.v4.nfrag_completed_sent);
2089 dpctl_print(dpctl_p, " v4 frags expired: %"PRIu64"\n",
2090 dpif_ipf_status.v4.nfrag_expired_sent);
2091 dpctl_print(dpctl_p, " v4 frags too small: %"PRIu64"\n",
2092 dpif_ipf_status.v4.nfrag_too_small);
2093 dpctl_print(dpctl_p, " v4 frags overlapped: %"PRIu64"\n",
2094 dpif_ipf_status.v4.nfrag_overlap);
2095 dpctl_print(dpctl_p, " v4 frags purged: %"PRIu64"\n",
2096 dpif_ipf_status.v4.nfrag_purged);
2097
2098 dpctl_print(dpctl_p, " min v6 frag size: %u\n",
2099 dpif_ipf_status.v6.min_frag_size);
2100 dpctl_print(dpctl_p, " v6 frags accepted: %"PRIu64"\n",
2101 dpif_ipf_status.v6.nfrag_accepted);
2102 dpctl_print(dpctl_p, " v6 frags completed: %"PRIu64"\n",
2103 dpif_ipf_status.v6.nfrag_completed_sent);
2104 dpctl_print(dpctl_p, " v6 frags expired: %"PRIu64"\n",
2105 dpif_ipf_status.v6.nfrag_expired_sent);
2106 dpctl_print(dpctl_p, " v6 frags too small: %"PRIu64"\n",
2107 dpif_ipf_status.v6.nfrag_too_small);
2108 dpctl_print(dpctl_p, " v6 frags overlapped: %"PRIu64"\n",
2109 dpif_ipf_status.v6.nfrag_overlap);
2110 dpctl_print(dpctl_p, " v6 frags purged: %"PRIu64"\n",
2111 dpif_ipf_status.v6.nfrag_purged);
2112 } else {
2113 dpctl_error(dpctl_p, error,
2114 "ipf status could not be retrieved");
2115 return error;
2116 }
2117
2118 if (dpctl_p->verbosity) {
2119 dpctl_dump_ipf(dpif, dpctl_p);
2120 }
2121
2122 dpif_close(dpif);
2123 }
2124
2125 return error;
2126 }
2127
2128 /* Undocumented commands for unit testing. */
2129
2130 static int
2131 dpctl_parse_actions(int argc, const char *argv[], struct dpctl_params* dpctl_p)
2132 {
2133 int i, error = 0;
2134
2135 for (i = 1; i < argc; i++) {
2136 struct ofpbuf actions;
2137 struct ds s;
2138
2139 ofpbuf_init(&actions, 0);
2140 error = odp_actions_from_string(argv[i], NULL, &actions);
2141
2142 if (error) {
2143 ofpbuf_uninit(&actions);
2144 dpctl_error(dpctl_p, error, "odp_actions_from_string");
2145 return error;
2146 }
2147
2148 ds_init(&s);
2149 format_odp_actions(&s, actions.data, actions.size, NULL);
2150 dpctl_print(dpctl_p, "%s\n", ds_cstr(&s));
2151 ds_destroy(&s);
2152
2153 ofpbuf_uninit(&actions);
2154 }
2155
2156 return error;
2157 }
2158
2159 struct actions_for_flow {
2160 struct hmap_node hmap_node;
2161 struct flow flow;
2162 struct ofpbuf actions;
2163 };
2164
2165 static struct actions_for_flow *
2166 get_actions_for_flow(struct hmap *actions_per_flow, const struct flow *flow)
2167 {
2168 uint32_t hash = flow_hash(flow, 0);
2169 struct actions_for_flow *af;
2170
2171 HMAP_FOR_EACH_WITH_HASH (af, hmap_node, hash, actions_per_flow) {
2172 if (flow_equal(&af->flow, flow)) {
2173 return af;
2174 }
2175 }
2176
2177 af = xmalloc(sizeof *af);
2178 af->flow = *flow;
2179 ofpbuf_init(&af->actions, 0);
2180 hmap_insert(actions_per_flow, &af->hmap_node, hash);
2181 return af;
2182 }
2183
2184 static int
2185 compare_actions_for_flow(const void *a_, const void *b_)
2186 {
2187 struct actions_for_flow *const *a = a_;
2188 struct actions_for_flow *const *b = b_;
2189
2190 return flow_compare_3way(&(*a)->flow, &(*b)->flow);
2191 }
2192
2193 static int
2194 compare_output_actions(const void *a_, const void *b_)
2195 {
2196 const struct nlattr *a = a_;
2197 const struct nlattr *b = b_;
2198 uint32_t a_port = nl_attr_get_u32(a);
2199 uint32_t b_port = nl_attr_get_u32(b);
2200
2201 return a_port < b_port ? -1 : a_port > b_port;
2202 }
2203
2204 static void
2205 sort_output_actions__(struct nlattr *first, struct nlattr *end)
2206 {
2207 size_t bytes = (uint8_t *) end - (uint8_t *) first;
2208 size_t n = bytes / NL_A_U32_SIZE;
2209
2210 ovs_assert(bytes % NL_A_U32_SIZE == 0);
2211 qsort(first, n, NL_A_U32_SIZE, compare_output_actions);
2212 }
2213
2214 static void
2215 sort_output_actions(struct nlattr *actions, size_t length)
2216 {
2217 struct nlattr *first_output = NULL;
2218 struct nlattr *a;
2219 int left;
2220
2221 NL_ATTR_FOR_EACH (a, left, actions, length) {
2222 if (nl_attr_type(a) == OVS_ACTION_ATTR_OUTPUT) {
2223 if (!first_output) {
2224 first_output = a;
2225 }
2226 } else {
2227 if (first_output) {
2228 sort_output_actions__(first_output, a);
2229 first_output = NULL;
2230 }
2231 }
2232 }
2233 if (first_output) {
2234 uint8_t *end = (uint8_t *) actions + length;
2235 sort_output_actions__(first_output,
2236 ALIGNED_CAST(struct nlattr *, end));
2237 }
2238 }
2239
2240 /* usage: "ovs-dpctl normalize-actions FLOW ACTIONS" where FLOW and ACTIONS
2241 * have the syntax used by "ovs-dpctl dump-flows".
2242 *
2243 * This command prints ACTIONS in a format that shows what happens for each
2244 * VLAN, independent of the order of the ACTIONS. For example, there is more
2245 * than one way to output a packet on VLANs 9 and 11, but this command will
2246 * print the same output for any form.
2247 *
2248 * The idea here generalizes beyond VLANs (e.g. to setting other fields) but
2249 * so far the implementation only covers VLANs. */
2250 static int
2251 dpctl_normalize_actions(int argc, const char *argv[],
2252 struct dpctl_params *dpctl_p)
2253 {
2254 struct simap port_names;
2255 struct ofpbuf keybuf;
2256 struct flow flow;
2257 struct ofpbuf odp_actions;
2258 struct hmap actions_per_flow;
2259 struct actions_for_flow **afs;
2260 struct actions_for_flow *af;
2261 struct nlattr *a;
2262 size_t n_afs;
2263 struct ds s;
2264 int left;
2265 int i, error;
2266 int encaps = 0;
2267
2268 ds_init(&s);
2269
2270 simap_init(&port_names);
2271 for (i = 3; i < argc; i++) {
2272 char name[16];
2273 int number;
2274
2275 if (ovs_scan(argv[i], "%15[^=]=%d", name, &number)) {
2276 uintptr_t n = number;
2277 simap_put(&port_names, name, n);
2278 } else {
2279 dpctl_error(dpctl_p, 0, "%s: expected NAME=NUMBER", argv[i]);
2280 error = EINVAL;
2281 goto out;
2282 }
2283 }
2284
2285 /* Parse flow key. */
2286 ofpbuf_init(&keybuf, 0);
2287 char *error_s;
2288 error = odp_flow_from_string(argv[1], &port_names, &keybuf, NULL,
2289 &error_s);
2290 if (error) {
2291 dpctl_error(dpctl_p, error, "odp_flow_key_from_string (%s)", error_s);
2292 free(error_s);
2293 goto out_freekeybuf;
2294 }
2295
2296 ds_clear(&s);
2297 odp_flow_format(keybuf.data, keybuf.size, NULL, 0, NULL,
2298 &s, dpctl_p->verbosity);
2299 dpctl_print(dpctl_p, "input flow: %s\n", ds_cstr(&s));
2300
2301 error = odp_flow_key_to_flow(keybuf.data, keybuf.size, &flow, &error_s);
2302 if (error) {
2303 dpctl_error(dpctl_p, error, "odp_flow_key_to_flow failed (%s)",
2304 error_s ? error_s : "reason unknown");
2305 free(error_s);
2306 goto out_freekeybuf;
2307 }
2308
2309 /* Parse actions. */
2310 ofpbuf_init(&odp_actions, 0);
2311 error = odp_actions_from_string(argv[2], &port_names, &odp_actions);
2312 if (error) {
2313 dpctl_error(dpctl_p, error, "odp_actions_from_string");
2314 goto out_freeactions;
2315 }
2316
2317 if (dpctl_p->verbosity) {
2318 ds_clear(&s);
2319 format_odp_actions(&s, odp_actions.data, odp_actions.size, NULL);
2320 dpctl_print(dpctl_p, "input actions: %s\n", ds_cstr(&s));
2321 }
2322
2323 hmap_init(&actions_per_flow);
2324 NL_ATTR_FOR_EACH (a, left, odp_actions.data, odp_actions.size) {
2325 const struct ovs_action_push_vlan *push;
2326 switch(nl_attr_type(a)) {
2327 case OVS_ACTION_ATTR_POP_VLAN:
2328 flow_pop_vlan(&flow, NULL);
2329 continue;
2330
2331 case OVS_ACTION_ATTR_PUSH_VLAN:
2332 flow_push_vlan_uninit(&flow, NULL);
2333 push = nl_attr_get_unspec(a, sizeof *push);
2334 flow.vlans[0].tpid = push->vlan_tpid;
2335 flow.vlans[0].tci = push->vlan_tci;
2336 continue;
2337 }
2338
2339 af = get_actions_for_flow(&actions_per_flow, &flow);
2340 nl_msg_put_unspec(&af->actions, nl_attr_type(a),
2341 nl_attr_get(a), nl_attr_get_size(a));
2342 }
2343
2344 n_afs = hmap_count(&actions_per_flow);
2345 afs = xmalloc(n_afs * sizeof *afs);
2346 i = 0;
2347 HMAP_FOR_EACH (af, hmap_node, &actions_per_flow) {
2348 afs[i++] = af;
2349 }
2350
2351 ovs_assert(i == n_afs);
2352 hmap_destroy(&actions_per_flow);
2353
2354 qsort(afs, n_afs, sizeof *afs, compare_actions_for_flow);
2355
2356 for (i = 0; i < n_afs; i++) {
2357 af = afs[i];
2358 sort_output_actions(af->actions.data, af->actions.size);
2359
2360 for (encaps = 0; encaps < FLOW_MAX_VLAN_HEADERS; encaps ++) {
2361 union flow_vlan_hdr *vlan = &af->flow.vlans[encaps];
2362 if (vlan->tci != htons(0)) {
2363 dpctl_print(dpctl_p, "vlan(");
2364 if (vlan->tpid != htons(ETH_TYPE_VLAN)) {
2365 dpctl_print(dpctl_p, "tpid=0x%04"PRIx16",", vlan->tpid);
2366 }
2367 dpctl_print(dpctl_p, "vid=%"PRIu16",pcp=%d): ",
2368 vlan_tci_to_vid(vlan->tci),
2369 vlan_tci_to_pcp(vlan->tci));
2370 } else {
2371 if (encaps == 0) {
2372 dpctl_print(dpctl_p, "no vlan: ");
2373 }
2374 break;
2375 }
2376 }
2377
2378 if (eth_type_mpls(af->flow.dl_type)) {
2379 dpctl_print(dpctl_p, "mpls(label=%"PRIu32",tc=%d,ttl=%d): ",
2380 mpls_lse_to_label(af->flow.mpls_lse[0]),
2381 mpls_lse_to_tc(af->flow.mpls_lse[0]),
2382 mpls_lse_to_ttl(af->flow.mpls_lse[0]));
2383 } else {
2384 dpctl_print(dpctl_p, "no mpls: ");
2385 }
2386
2387 ds_clear(&s);
2388 format_odp_actions(&s, af->actions.data, af->actions.size, NULL);
2389 dpctl_puts(dpctl_p, false, ds_cstr(&s));
2390
2391 ofpbuf_uninit(&af->actions);
2392 free(af);
2393 }
2394 free(afs);
2395
2396
2397 out_freeactions:
2398 ofpbuf_uninit(&odp_actions);
2399 out_freekeybuf:
2400 ofpbuf_uninit(&keybuf);
2401 out:
2402 simap_destroy(&port_names);
2403 ds_destroy(&s);
2404
2405 return error;
2406 }
2407 \f
2408 static const struct dpctl_command all_commands[] = {
2409 { "add-dp", "dp [iface...]", 1, INT_MAX, dpctl_add_dp, DP_RW },
2410 { "del-dp", "dp", 1, 1, dpctl_del_dp, DP_RW },
2411 { "add-if", "dp iface...", 2, INT_MAX, dpctl_add_if, DP_RW },
2412 { "del-if", "dp iface...", 2, INT_MAX, dpctl_del_if, DP_RW },
2413 { "set-if", "dp iface...", 2, INT_MAX, dpctl_set_if, DP_RW },
2414 { "dump-dps", "", 0, 0, dpctl_dump_dps, DP_RO },
2415 { "show", "[dp...]", 0, INT_MAX, dpctl_show, DP_RO },
2416 { "dump-flows", "[dp] [filter=..] [type=..]",
2417 0, 3, dpctl_dump_flows, DP_RO },
2418 { "add-flow", "[dp] flow actions", 2, 3, dpctl_add_flow, DP_RW },
2419 { "mod-flow", "[dp] flow actions", 2, 3, dpctl_mod_flow, DP_RW },
2420 { "get-flow", "[dp] ufid", 1, 2, dpctl_get_flow, DP_RO },
2421 { "del-flow", "[dp] flow", 1, 2, dpctl_del_flow, DP_RW },
2422 { "del-flows", "[dp]", 0, 1, dpctl_del_flows, DP_RW },
2423 { "dump-conntrack", "[dp] [zone=N]", 0, 2, dpctl_dump_conntrack, DP_RO },
2424 { "flush-conntrack", "[dp] [zone=N] [ct-tuple]", 0, 3,
2425 dpctl_flush_conntrack, DP_RW },
2426 { "ct-stats-show", "[dp] [zone=N]",
2427 0, 3, dpctl_ct_stats_show, DP_RO },
2428 { "ct-bkts", "[dp] [gt=N]", 0, 2, dpctl_ct_bkts, DP_RO },
2429 { "ct-set-maxconns", "[dp] maxconns", 1, 2, dpctl_ct_set_maxconns, DP_RW },
2430 { "ct-get-maxconns", "[dp]", 0, 1, dpctl_ct_get_maxconns, DP_RO },
2431 { "ct-get-nconns", "[dp]", 0, 1, dpctl_ct_get_nconns, DP_RO },
2432 { "ct-set-limits", "[dp] [default=L] [zone=N,limit=L]...", 1, INT_MAX,
2433 dpctl_ct_set_limits, DP_RO },
2434 { "ct-del-limits", "[dp] zone=N1[,N2]...", 1, 2, dpctl_ct_del_limits,
2435 DP_RO },
2436 { "ct-get-limits", "[dp] [zone=N1[,N2]...]", 0, 2, dpctl_ct_get_limits,
2437 DP_RO },
2438 { "ipf-set-enabled", "[dp] v4|v6", 1, 2, dpctl_ipf_set_enabled, DP_RW },
2439 { "ipf-set-disabled", "[dp] v4|v6", 1, 2, dpctl_ipf_set_disabled, DP_RW },
2440 { "ipf-set-min-frag", "[dp] v4|v6 minfragment", 2, 3,
2441 dpctl_ipf_set_min_frag, DP_RW },
2442 { "ipf-set-max-nfrags", "[dp] maxfrags", 1, 2,
2443 dpctl_ipf_set_max_nfrags, DP_RW },
2444 { "ipf-get-status", "[dp]", 0, 1, dpctl_ct_ipf_get_status,
2445 DP_RO },
2446 { "help", "", 0, INT_MAX, dpctl_help, DP_RO },
2447 { "list-commands", "", 0, INT_MAX, dpctl_list_commands, DP_RO },
2448
2449 /* Undocumented commands for testing. */
2450 { "parse-actions", "actions", 1, INT_MAX, dpctl_parse_actions, DP_RO },
2451 { "normalize-actions", "actions",
2452 2, INT_MAX, dpctl_normalize_actions, DP_RO },
2453
2454 { NULL, NULL, 0, 0, NULL, DP_RO },
2455 };
2456
2457 static const struct dpctl_command *get_all_dpctl_commands(void)
2458 {
2459 return all_commands;
2460 }
2461
2462 /* Runs the command designated by argv[0] within the command table specified by
2463 * 'commands', which must be terminated by a command whose 'name' member is a
2464 * null pointer. */
2465 int
2466 dpctl_run_command(int argc, const char *argv[], struct dpctl_params *dpctl_p)
2467 {
2468 const struct dpctl_command *p;
2469 if (argc < 1) {
2470 dpctl_error(dpctl_p, 0, "missing command name; use --help for help");
2471 return EINVAL;
2472 }
2473
2474 for (p = all_commands; p->name != NULL; p++) {
2475 if (!strcmp(p->name, argv[0])) {
2476 int n_arg = argc - 1;
2477 if (n_arg < p->min_args) {
2478 dpctl_error(dpctl_p, 0,
2479 "'%s' command requires at least %d arguments",
2480 p->name, p->min_args);
2481 return EINVAL;
2482 } else if (n_arg > p->max_args) {
2483 dpctl_error(dpctl_p, 0,
2484 "'%s' command takes at most %d arguments",
2485 p->name, p->max_args);
2486 return EINVAL;
2487 } else {
2488 if (p->mode == DP_RW && dpctl_p->read_only) {
2489 dpctl_error(dpctl_p, 0,
2490 "'%s' command does not work in read only mode",
2491 p->name);
2492 return EINVAL;
2493 }
2494 return p->handler(argc, argv, dpctl_p);
2495 }
2496 }
2497 }
2498
2499 dpctl_error(dpctl_p, 0, "unknown command '%s'; use --help for help",
2500 argv[0]);
2501 return EINVAL;
2502 }
2503 \f
2504 static void
2505 dpctl_unixctl_print(void *userdata, bool error OVS_UNUSED, const char *msg)
2506 {
2507 struct ds *ds = userdata;
2508 ds_put_cstr(ds, msg);
2509 }
2510
2511 static void
2512 dpctl_unixctl_handler(struct unixctl_conn *conn, int argc, const char *argv[],
2513 void *aux)
2514 {
2515 struct ds ds = DS_EMPTY_INITIALIZER;
2516 bool error = false;
2517
2518 struct dpctl_params dpctl_p = {
2519 .is_appctl = true,
2520 .output = dpctl_unixctl_print,
2521 .aux = &ds,
2522 };
2523
2524 /* Parse options (like getopt). Unfortunately it does
2525 * not seem a good idea to call getopt_long() here, since it uses global
2526 * variables */
2527 bool set_names = false;
2528 while (argc > 1 && !error) {
2529 const char *arg = argv[1];
2530 if (!strncmp(arg, "--", 2)) {
2531 /* Long option */
2532 if (!strcmp(arg, "--statistics")) {
2533 dpctl_p.print_statistics = true;
2534 } else if (!strcmp(arg, "--clear")) {
2535 dpctl_p.zero_statistics = true;
2536 } else if (!strcmp(arg, "--may-create")) {
2537 dpctl_p.may_create = true;
2538 } else if (!strcmp(arg, "--more")) {
2539 dpctl_p.verbosity++;
2540 } else if (!strcmp(arg, "--names")) {
2541 dpctl_p.names = true;
2542 set_names = true;
2543 } else if (!strcmp(arg, "--no-names")) {
2544 dpctl_p.names = false;
2545 set_names = true;
2546 } else {
2547 ds_put_format(&ds, "Unrecognized option %s", argv[1]);
2548 error = true;
2549 }
2550 } else if (arg[0] == '-' && arg[1] != '\0') {
2551 /* Short option[s] */
2552 const char *opt = &arg[1];
2553
2554 while (*opt && !error) {
2555 switch (*opt) {
2556 case 'm':
2557 dpctl_p.verbosity++;
2558 break;
2559 case 's':
2560 dpctl_p.print_statistics = true;
2561 break;
2562 default:
2563 ds_put_format(&ds, "Unrecognized option -%c", *opt);
2564 error = true;
2565 break;
2566 }
2567 opt++;
2568 }
2569 } else {
2570 /* Doesn't start with -, not an option */
2571 break;
2572 }
2573
2574 if (error) {
2575 break;
2576 }
2577 argv++;
2578 argc--;
2579 }
2580 if (!set_names) {
2581 dpctl_p.names = dpctl_p.verbosity > 0;
2582 }
2583 VLOG_INFO("set_names=%d verbosity=%d names=%d", set_names,
2584 dpctl_p.verbosity, dpctl_p.names);
2585
2586 if (!error) {
2587 dpctl_command_handler *handler = (dpctl_command_handler *) aux;
2588 error = handler(argc, argv, &dpctl_p) != 0;
2589 }
2590
2591 if (error) {
2592 unixctl_command_reply_error(conn, ds_cstr(&ds));
2593 } else {
2594 unixctl_command_reply(conn, ds_cstr(&ds));
2595 }
2596
2597 ds_destroy(&ds);
2598 }
2599
2600 void
2601 dpctl_unixctl_register(void)
2602 {
2603 const struct dpctl_command *p;
2604
2605 for (p = all_commands; p->name != NULL; p++) {
2606 if (strcmp(p->name, "help")) {
2607 char *cmd_name = xasprintf("dpctl/%s", p->name);
2608 unixctl_command_register(cmd_name,
2609 p->usage,
2610 p->min_args,
2611 p->max_args,
2612 dpctl_unixctl_handler,
2613 p->handler);
2614 free(cmd_name);
2615 }
2616 }
2617 }