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