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