]> git.proxmox.com Git - mirror_ovs.git/blob - lib/dpctl.c
ovs-dpctl: New --names option to use port names in flow dumps.
[mirror_ovs.git] / lib / dpctl.c
1 /*
2 * Copyright (c) 2008-2017 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 "packets.h"
44 #include "openvswitch/shash.h"
45 #include "simap.h"
46 #include "smap.h"
47 #include "sset.h"
48 #include "timeval.h"
49 #include "unixctl.h"
50 #include "util.h"
51 #include "openvswitch/ofp-parse.h"
52 #include "openvswitch/vlog.h"
53 VLOG_DEFINE_THIS_MODULE(dpctl);
54
55 typedef int dpctl_command_handler(int argc, const char *argv[],
56 struct dpctl_params *);
57 struct dpctl_command {
58 const char *name;
59 const char *usage;
60 int min_args;
61 int max_args;
62 dpctl_command_handler *handler;
63 enum { DP_RO, DP_RW} mode;
64 };
65 static const struct dpctl_command *get_all_dpctl_commands(void);
66 static void dpctl_print(struct dpctl_params *dpctl_p, const char *fmt, ...)
67 OVS_PRINTF_FORMAT(2, 3);
68 static void dpctl_error(struct dpctl_params* dpctl_p, int err_no,
69 const char *fmt, ...)
70 OVS_PRINTF_FORMAT(3, 4);
71
72 static void
73 dpctl_puts(struct dpctl_params *dpctl_p, bool error, const char *string)
74 {
75 dpctl_p->output(dpctl_p->aux, error, string);
76 }
77
78 static void
79 dpctl_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
92 static void
93 dpctl_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
123 static int dpctl_add_if(int argc, const char *argv[], struct dpctl_params *);
124
125 static int
126 if_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. */
134 static char *
135 get_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
169 static int
170 parsed_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
188 static int
189 dpctl_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
207 static int
208 dpctl_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
228 static int
229 dpctl_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
304 next_destroy_args:
305 netdev_close(netdev);
306 smap_destroy(&args);
307 next:
308 free(argcopy);
309 if (error) {
310 lasterror = error;
311 }
312 }
313 dpif_close(dpif);
314
315 return lasterror;
316 }
317
318 static int
319 dpctl_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;
393 goto next_destroy_args;
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;
400 goto next_destroy_args;
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. */
410 char *err_s = NULL;
411 error = netdev_set_config(netdev, &args, &err_s);
412 if (err_s || error) {
413 dpctl_error(dpctl_p, error, "%s",
414 err_s ? err_s : "Error updating configuration");
415 free(err_s);
416 }
417 if (error) {
418 goto next_destroy_args;
419 }
420
421 next_destroy_args:
422 smap_destroy(&args);
423 next:
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
436 static bool
437 get_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
452 static int
453 dpctl_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
485 static void
486 print_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
496 static void
497 print_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
513 /* qsort comparison function. */
514 static int
515 compare_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
525 static void
526 show_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
548 odp_port_t *port_nos = NULL;
549 size_t allocated_port_nos = 0, n_port_nos = 0;
550 DPIF_PORT_FOR_EACH (&dpif_port, &dump, dpif) {
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
560 if (port_nos) {
561 qsort(port_nos, n_port_nos, sizeof *port_nos, compare_port_nos);
562 }
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
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) {
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 ? ',' : ':',
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));
614 dpif_port_destroy(&dpif_port);
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 }
647 dpif_port_destroy(&dpif_port);
648 }
649
650 free(port_nos);
651 }
652
653 typedef void (*dps_for_each_cb)(struct dpif *, struct dpctl_params *);
654
655 static int
656 dps_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);
660 int error, openerror = 0, enumerror = 0;
661 const char *type, *name;
662 bool at_least_one = false;
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) {
669 enumerror = error;
670 }
671
672 SSET_FOR_EACH (name, &dpif_names) {
673 struct dpif *dpif;
674
675 at_least_one = true;
676 error = dpif_open(name, type, &dpif);
677 if (!error) {
678 cb(dpif, dpctl_p);
679 dpif_close(dpif);
680 } else {
681 openerror = error;
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
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 }
702 }
703
704 static int
705 dpctl_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);
717 dpif_close(dpif);
718 } else {
719 dpctl_error(dpctl_p, error, "opening datapath %s failed",
720 name);
721 lasterror = error;
722 }
723 }
724 } else {
725 lasterror = dps_for_each(dpctl_p, show_dpif);
726 }
727
728 return lasterror;
729 }
730
731 static void
732 dump_cb(struct dpif *dpif, struct dpctl_params *dpctl_p)
733 {
734 dpctl_print(dpctl_p, "%s\n", dpif_name(dpif));
735 }
736
737 static int
738 dpctl_dump_dps(int argc OVS_UNUSED, const char *argv[] OVS_UNUSED,
739 struct dpctl_params *dpctl_p)
740 {
741 return dps_for_each(dpctl_p, dump_cb);
742 }
743
744 static void
745 format_dpif_flow(struct ds *ds, const struct dpif_flow *f, struct hmap *ports,
746 char *type, struct dpctl_params *dpctl_p)
747 {
748 if (dpctl_p->verbosity && f->ufid_present) {
749 odp_format_ufid(&f->ufid, ds);
750 ds_put_cstr(ds, ", ");
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);
757 if (dpctl_p->verbosity && !type && f->offloaded) {
758 ds_put_cstr(ds, ", offloaded:yes");
759 }
760 ds_put_cstr(ds, ", actions:");
761 format_odp_actions(ds, f->actions, f->actions_len);
762 }
763
764 static char *supported_dump_types[] = {
765 "offloaded",
766 "ovs",
767 };
768
769 static struct hmap *
770 dpctl_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
789 static void
790 dpctl_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
799 static int
800 dpctl_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;
807 char *type = NULL;
808 struct flow flow_filter;
809 struct flow_wildcards wc_filter;
810
811 struct dpif_flow_dump_thread *flow_dump_thread;
812 struct dpif_flow_dump *flow_dump;
813 struct dpif_flow f;
814 int pmd_id = PMD_ID_NULL;
815 int lastargc = 0;
816 int error;
817
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 }
825 }
826
827 name = (argc > 1) ? xstrdup(argv[1]) : get_one_dp(dpctl_p);
828 if (!name) {
829 error = EINVAL;
830 goto out_free;
831 }
832
833 error = parsed_dpif_open(name, false, &dpif);
834 free(name);
835 if (error) {
836 dpctl_error(dpctl_p, error, "opening datapath");
837 goto out_free;
838 }
839
840 struct hmap *portno_names = dpctl_get_portno_names(dpif, dpctl_p);
841
842 if (filter) {
843 struct ofputil_port_map port_map;
844 ofputil_port_map_init(&port_map);
845
846 struct dpif_port_dump port_dump;
847 struct dpif_port dpif_port;
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);
856 if (err) {
857 dpctl_error(dpctl_p, 0, "Failed to parse filter (%s)", err);
858 free(err);
859 error = EINVAL;
860 goto out_dpifclose;
861 }
862 }
863
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
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
884 ds_init(&ds);
885 memset(&f, 0, sizeof f);
886 flow_dump = dpif_flow_dump_create(dpif, false, (type ? type : "dpctl"));
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);
896 odp_flow_key_to_mask(f.mask, f.mask_len, &wc, &flow);
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);
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 }
922 format_dpif_flow(&ds, &f, portno_names, type, dpctl_p);
923
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
934 out_dpifclose:
935 dpctl_free_portno_names(portno_names);
936 dpif_close(dpif);
937 out_free:
938 free(filter);
939 free(type);
940 return error;
941 }
942
943 static int
944 dpctl_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;
956 ovs_u128 ufid;
957 bool ufid_present;
958 char *dp_name;
959 struct simap port_names;
960 int n, error;
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
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 }
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 }
1003
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
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
1027 out_freeactions:
1028 ofpbuf_uninit(&actions);
1029 out_freekeymask:
1030 ofpbuf_uninit(&mask);
1031 ofpbuf_uninit(&key);
1032 dpif_close(dpif);
1033 return error;
1034 }
1035
1036 static int
1037 dpctl_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
1042 static int
1043 dpctl_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
1058 static int
1059 dpctl_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;
1063 struct dpif *dpif;
1064 char *dp_name;
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);
1083
1084 struct hmap *portno_names = dpctl_get_portno_names(dpif, dpctl_p);
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
1092 /* In case of PMD will be returned flow from first PMD thread with match. */
1093 error = dpif_flow_get(dpif, NULL, 0, &ufid, PMD_ID_NULL, &buf, &flow);
1094 if (error) {
1095 dpctl_error(dpctl_p, error, "getting flow");
1096 goto out;
1097 }
1098
1099 ds_init(&ds);
1100 format_dpif_flow(&ds, &flow, portno_names, NULL, dpctl_p);
1101 dpctl_print(dpctl_p, "%s\n", ds_cstr(&ds));
1102 ds_destroy(&ds);
1103
1104 out:
1105 dpctl_free_portno_names(portno_names);
1106 ofpbuf_uninit(&buf);
1107 dpif_close(dpif);
1108 return error;
1109 }
1110
1111 static int
1112 dpctl_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;
1121 ovs_u128 ufid;
1122 bool ufid_present;
1123 char *dp_name;
1124 struct simap port_names;
1125 int n, error;
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
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
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
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
1167 if (error) {
1168 dpctl_error(dpctl_p, error, "deleting flow");
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 }
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
1189 out:
1190 ofpbuf_uninit(&mask);
1191 ofpbuf_uninit(&key);
1192 simap_destroy(&port_names);
1193 dpif_close(dpif);
1194 return error;
1195 }
1196
1197 static int
1198 dpctl_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
1223 static int
1224 dpctl_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 }
1230
1231 return 0;
1232 }
1233
1234 static int
1235 dpctl_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
1251 return 0;
1252 }
1253
1254 static int
1255 dpctl_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
1302 static int
1303 dpctl_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 }
1331 \f
1332 /* Undocumented commands for unit testing. */
1333
1334 static int
1335 dpctl_parse_actions(int argc, const char *argv[], struct dpctl_params* dpctl_p)
1336 {
1337 int i, error = 0;
1338
1339 for (i = 1; i < argc; i++) {
1340 struct ofpbuf actions;
1341 struct ds s;
1342
1343 ofpbuf_init(&actions, 0);
1344 error = odp_actions_from_string(argv[i], NULL, &actions);
1345
1346 if (error) {
1347 ofpbuf_uninit(&actions);
1348 dpctl_error(dpctl_p, error, "odp_actions_from_string");
1349 return error;
1350 }
1351
1352 ds_init(&s);
1353 format_odp_actions(&s, actions.data, actions.size);
1354 dpctl_print(dpctl_p, "%s\n", ds_cstr(&s));
1355 ds_destroy(&s);
1356
1357 ofpbuf_uninit(&actions);
1358 }
1359
1360 return error;
1361 }
1362
1363 struct actions_for_flow {
1364 struct hmap_node hmap_node;
1365 struct flow flow;
1366 struct ofpbuf actions;
1367 };
1368
1369 static struct actions_for_flow *
1370 get_actions_for_flow(struct hmap *actions_per_flow, const struct flow *flow)
1371 {
1372 uint32_t hash = flow_hash(flow, 0);
1373 struct actions_for_flow *af;
1374
1375 HMAP_FOR_EACH_WITH_HASH (af, hmap_node, hash, actions_per_flow) {
1376 if (flow_equal(&af->flow, flow)) {
1377 return af;
1378 }
1379 }
1380
1381 af = xmalloc(sizeof *af);
1382 af->flow = *flow;
1383 ofpbuf_init(&af->actions, 0);
1384 hmap_insert(actions_per_flow, &af->hmap_node, hash);
1385 return af;
1386 }
1387
1388 static int
1389 compare_actions_for_flow(const void *a_, const void *b_)
1390 {
1391 struct actions_for_flow *const *a = a_;
1392 struct actions_for_flow *const *b = b_;
1393
1394 return flow_compare_3way(&(*a)->flow, &(*b)->flow);
1395 }
1396
1397 static int
1398 compare_output_actions(const void *a_, const void *b_)
1399 {
1400 const struct nlattr *a = a_;
1401 const struct nlattr *b = b_;
1402 uint32_t a_port = nl_attr_get_u32(a);
1403 uint32_t b_port = nl_attr_get_u32(b);
1404
1405 return a_port < b_port ? -1 : a_port > b_port;
1406 }
1407
1408 static void
1409 sort_output_actions__(struct nlattr *first, struct nlattr *end)
1410 {
1411 size_t bytes = (uint8_t *) end - (uint8_t *) first;
1412 size_t n = bytes / NL_A_U32_SIZE;
1413
1414 ovs_assert(bytes % NL_A_U32_SIZE == 0);
1415 qsort(first, n, NL_A_U32_SIZE, compare_output_actions);
1416 }
1417
1418 static void
1419 sort_output_actions(struct nlattr *actions, size_t length)
1420 {
1421 struct nlattr *first_output = NULL;
1422 struct nlattr *a;
1423 int left;
1424
1425 NL_ATTR_FOR_EACH (a, left, actions, length) {
1426 if (nl_attr_type(a) == OVS_ACTION_ATTR_OUTPUT) {
1427 if (!first_output) {
1428 first_output = a;
1429 }
1430 } else {
1431 if (first_output) {
1432 sort_output_actions__(first_output, a);
1433 first_output = NULL;
1434 }
1435 }
1436 }
1437 if (first_output) {
1438 uint8_t *end = (uint8_t *) actions + length;
1439 sort_output_actions__(first_output,
1440 ALIGNED_CAST(struct nlattr *, end));
1441 }
1442 }
1443
1444 /* usage: "ovs-dpctl normalize-actions FLOW ACTIONS" where FLOW and ACTIONS
1445 * have the syntax used by "ovs-dpctl dump-flows".
1446 *
1447 * This command prints ACTIONS in a format that shows what happens for each
1448 * VLAN, independent of the order of the ACTIONS. For example, there is more
1449 * than one way to output a packet on VLANs 9 and 11, but this command will
1450 * print the same output for any form.
1451 *
1452 * The idea here generalizes beyond VLANs (e.g. to setting other fields) but
1453 * so far the implementation only covers VLANs. */
1454 static int
1455 dpctl_normalize_actions(int argc, const char *argv[],
1456 struct dpctl_params *dpctl_p)
1457 {
1458 struct simap port_names;
1459 struct ofpbuf keybuf;
1460 struct flow flow;
1461 struct ofpbuf odp_actions;
1462 struct hmap actions_per_flow;
1463 struct actions_for_flow **afs;
1464 struct actions_for_flow *af;
1465 struct nlattr *a;
1466 size_t n_afs;
1467 struct ds s;
1468 int left;
1469 int i, error;
1470 int encaps = 0;
1471
1472 ds_init(&s);
1473
1474 simap_init(&port_names);
1475 for (i = 3; i < argc; i++) {
1476 char name[16];
1477 int number;
1478
1479 if (ovs_scan(argv[i], "%15[^=]=%d", name, &number)) {
1480 uintptr_t n = number;
1481 simap_put(&port_names, name, n);
1482 } else {
1483 dpctl_error(dpctl_p, 0, "%s: expected NAME=NUMBER", argv[i]);
1484 error = EINVAL;
1485 goto out;
1486 }
1487 }
1488
1489 /* Parse flow key. */
1490 ofpbuf_init(&keybuf, 0);
1491 error = odp_flow_from_string(argv[1], &port_names, &keybuf, NULL);
1492 if (error) {
1493 dpctl_error(dpctl_p, error, "odp_flow_key_from_string");
1494 goto out_freekeybuf;
1495 }
1496
1497 ds_clear(&s);
1498 odp_flow_format(keybuf.data, keybuf.size, NULL, 0, NULL,
1499 &s, dpctl_p->verbosity);
1500 dpctl_print(dpctl_p, "input flow: %s\n", ds_cstr(&s));
1501
1502 error = odp_flow_key_to_flow(keybuf.data, keybuf.size, &flow);
1503 if (error) {
1504 dpctl_error(dpctl_p, error, "odp_flow_key_to_flow");
1505 goto out_freekeybuf;
1506 }
1507
1508 /* Parse actions. */
1509 ofpbuf_init(&odp_actions, 0);
1510 error = odp_actions_from_string(argv[2], &port_names, &odp_actions);
1511 if (error) {
1512 dpctl_error(dpctl_p, error, "odp_actions_from_string");
1513 goto out_freeactions;
1514 }
1515
1516 if (dpctl_p->verbosity) {
1517 ds_clear(&s);
1518 format_odp_actions(&s, odp_actions.data, odp_actions.size);
1519 dpctl_print(dpctl_p, "input actions: %s\n", ds_cstr(&s));
1520 }
1521
1522 hmap_init(&actions_per_flow);
1523 NL_ATTR_FOR_EACH (a, left, odp_actions.data, odp_actions.size) {
1524 const struct ovs_action_push_vlan *push;
1525 switch(nl_attr_type(a)) {
1526 case OVS_ACTION_ATTR_POP_VLAN:
1527 flow_pop_vlan(&flow, NULL);
1528 continue;
1529
1530 case OVS_ACTION_ATTR_PUSH_VLAN:
1531 flow_push_vlan_uninit(&flow, NULL);
1532 push = nl_attr_get_unspec(a, sizeof *push);
1533 flow.vlans[0].tpid = push->vlan_tpid;
1534 flow.vlans[0].tci = push->vlan_tci;
1535 continue;
1536 }
1537
1538 af = get_actions_for_flow(&actions_per_flow, &flow);
1539 nl_msg_put_unspec(&af->actions, nl_attr_type(a),
1540 nl_attr_get(a), nl_attr_get_size(a));
1541 }
1542
1543 n_afs = hmap_count(&actions_per_flow);
1544 afs = xmalloc(n_afs * sizeof *afs);
1545 i = 0;
1546 HMAP_FOR_EACH (af, hmap_node, &actions_per_flow) {
1547 afs[i++] = af;
1548 }
1549
1550 ovs_assert(i == n_afs);
1551 hmap_destroy(&actions_per_flow);
1552
1553 qsort(afs, n_afs, sizeof *afs, compare_actions_for_flow);
1554
1555 for (i = 0; i < n_afs; i++) {
1556 struct actions_for_flow *af = afs[i];
1557
1558 sort_output_actions(af->actions.data, af->actions.size);
1559
1560 for (encaps = 0; encaps < FLOW_MAX_VLAN_HEADERS; encaps ++) {
1561 union flow_vlan_hdr *vlan = &af->flow.vlans[encaps];
1562 if (vlan->tci != htons(0)) {
1563 dpctl_print(dpctl_p, "vlan(");
1564 if (vlan->tpid != htons(ETH_TYPE_VLAN)) {
1565 dpctl_print(dpctl_p, "tpid=0x%04"PRIx16",", vlan->tpid);
1566 }
1567 dpctl_print(dpctl_p, "vid=%"PRIu16",pcp=%d): ",
1568 vlan_tci_to_vid(vlan->tci),
1569 vlan_tci_to_pcp(vlan->tci));
1570 } else {
1571 if (encaps == 0) {
1572 dpctl_print(dpctl_p, "no vlan: ");
1573 }
1574 break;
1575 }
1576 }
1577
1578 if (eth_type_mpls(af->flow.dl_type)) {
1579 dpctl_print(dpctl_p, "mpls(label=%"PRIu32",tc=%d,ttl=%d): ",
1580 mpls_lse_to_label(af->flow.mpls_lse[0]),
1581 mpls_lse_to_tc(af->flow.mpls_lse[0]),
1582 mpls_lse_to_ttl(af->flow.mpls_lse[0]));
1583 } else {
1584 dpctl_print(dpctl_p, "no mpls: ");
1585 }
1586
1587 ds_clear(&s);
1588 format_odp_actions(&s, af->actions.data, af->actions.size);
1589 dpctl_puts(dpctl_p, false, ds_cstr(&s));
1590
1591 ofpbuf_uninit(&af->actions);
1592 free(af);
1593 }
1594 free(afs);
1595
1596
1597 out_freeactions:
1598 ofpbuf_uninit(&odp_actions);
1599 out_freekeybuf:
1600 ofpbuf_uninit(&keybuf);
1601 out:
1602 simap_destroy(&port_names);
1603 ds_destroy(&s);
1604
1605 return error;
1606 }
1607 \f
1608 static const struct dpctl_command all_commands[] = {
1609 { "add-dp", "dp [iface...]", 1, INT_MAX, dpctl_add_dp, DP_RW },
1610 { "del-dp", "dp", 1, 1, dpctl_del_dp, DP_RW },
1611 { "add-if", "dp iface...", 2, INT_MAX, dpctl_add_if, DP_RW },
1612 { "del-if", "dp iface...", 2, INT_MAX, dpctl_del_if, DP_RW },
1613 { "set-if", "dp iface...", 2, INT_MAX, dpctl_set_if, DP_RW },
1614 { "dump-dps", "", 0, 0, dpctl_dump_dps, DP_RO },
1615 { "show", "[dp...]", 0, INT_MAX, dpctl_show, DP_RO },
1616 { "dump-flows", "[dp] [filter=..] [type=..]", 0, 3, dpctl_dump_flows, DP_RO },
1617 { "add-flow", "[dp] flow actions", 2, 3, dpctl_add_flow, DP_RW },
1618 { "mod-flow", "[dp] flow actions", 2, 3, dpctl_mod_flow, DP_RW },
1619 { "get-flow", "[dp] ufid", 1, 2, dpctl_get_flow, DP_RO },
1620 { "del-flow", "[dp] flow", 1, 2, dpctl_del_flow, DP_RW },
1621 { "del-flows", "[dp]", 0, 1, dpctl_del_flows, DP_RW },
1622 { "dump-conntrack", "[dp] [zone=N]", 0, 2, dpctl_dump_conntrack, DP_RO },
1623 { "flush-conntrack", "[dp] [zone=N]", 0, 2, dpctl_flush_conntrack, DP_RW },
1624 { "help", "", 0, INT_MAX, dpctl_help, DP_RO },
1625 { "list-commands", "", 0, INT_MAX, dpctl_list_commands, DP_RO },
1626
1627 /* Undocumented commands for testing. */
1628 { "parse-actions", "actions", 1, INT_MAX, dpctl_parse_actions, DP_RO },
1629 { "normalize-actions", "actions", 2, INT_MAX, dpctl_normalize_actions, DP_RO },
1630
1631 { NULL, NULL, 0, 0, NULL, DP_RO },
1632 };
1633
1634 static const struct dpctl_command *get_all_dpctl_commands(void)
1635 {
1636 return all_commands;
1637 }
1638
1639 /* Runs the command designated by argv[0] within the command table specified by
1640 * 'commands', which must be terminated by a command whose 'name' member is a
1641 * null pointer. */
1642 int
1643 dpctl_run_command(int argc, const char *argv[], struct dpctl_params *dpctl_p)
1644 {
1645 const struct dpctl_command *p;
1646
1647 if (argc < 1) {
1648 dpctl_error(dpctl_p, 0, "missing command name; use --help for help");
1649 return EINVAL;
1650 }
1651
1652 for (p = all_commands; p->name != NULL; p++) {
1653 if (!strcmp(p->name, argv[0])) {
1654 int n_arg = argc - 1;
1655 if (n_arg < p->min_args) {
1656 dpctl_error(dpctl_p, 0,
1657 "'%s' command requires at least %d arguments",
1658 p->name, p->min_args);
1659 return EINVAL;
1660 } else if (n_arg > p->max_args) {
1661 dpctl_error(dpctl_p, 0,
1662 "'%s' command takes at most %d arguments",
1663 p->name, p->max_args);
1664 return EINVAL;
1665 } else {
1666 if (p->mode == DP_RW && dpctl_p->read_only) {
1667 dpctl_error(dpctl_p, 0,
1668 "'%s' command does not work in read only mode",
1669 p->name);
1670 return EINVAL;
1671 }
1672 return p->handler(argc, argv, dpctl_p);
1673 }
1674 }
1675 }
1676
1677 dpctl_error(dpctl_p, 0, "unknown command '%s'; use --help for help",
1678 argv[0]);
1679 return EINVAL;
1680 }
1681 \f
1682 static void
1683 dpctl_unixctl_print(void *userdata, bool error OVS_UNUSED, const char *msg)
1684 {
1685 struct ds *ds = userdata;
1686 ds_put_cstr(ds, msg);
1687 }
1688
1689 static void
1690 dpctl_unixctl_handler(struct unixctl_conn *conn, int argc, const char *argv[],
1691 void *aux)
1692 {
1693 struct ds ds = DS_EMPTY_INITIALIZER;
1694 bool error = false;
1695
1696 struct dpctl_params dpctl_p = {
1697 .is_appctl = true,
1698 .output = dpctl_unixctl_print,
1699 .aux = &ds,
1700 };
1701
1702 /* Parse options (like getopt). Unfortunately it does
1703 * not seem a good idea to call getopt_long() here, since it uses global
1704 * variables */
1705 bool set_names = false;
1706 while (argc > 1 && !error) {
1707 const char *arg = argv[1];
1708 if (!strncmp(arg, "--", 2)) {
1709 /* Long option */
1710 if (!strcmp(arg, "--statistics")) {
1711 dpctl_p.print_statistics = true;
1712 } else if (!strcmp(arg, "--clear")) {
1713 dpctl_p.zero_statistics = true;
1714 } else if (!strcmp(arg, "--may-create")) {
1715 dpctl_p.may_create = true;
1716 } else if (!strcmp(arg, "--more")) {
1717 dpctl_p.verbosity++;
1718 } else if (!strcmp(arg, "--names")) {
1719 dpctl_p.names = true;
1720 set_names = true;
1721 } else if (!strcmp(arg, "--no-names")) {
1722 dpctl_p.names = false;
1723 set_names = true;
1724 } else {
1725 ds_put_format(&ds, "Unrecognized option %s", argv[1]);
1726 error = true;
1727 }
1728 } else if (arg[0] == '-' && arg[1] != '\0') {
1729 /* Short option[s] */
1730 const char *opt = &arg[1];
1731
1732 while (*opt && !error) {
1733 switch (*opt) {
1734 case 'm':
1735 dpctl_p.verbosity++;
1736 break;
1737 case 's':
1738 dpctl_p.print_statistics = true;
1739 break;
1740 default:
1741 ds_put_format(&ds, "Unrecognized option -%c", *opt);
1742 error = true;
1743 break;
1744 }
1745 opt++;
1746 }
1747 } else {
1748 /* Doesn't start with -, not an option */
1749 break;
1750 }
1751
1752 if (error) {
1753 break;
1754 }
1755 argv++;
1756 argc--;
1757 }
1758 if (!set_names) {
1759 dpctl_p.names = dpctl_p.verbosity > 0;
1760 }
1761 VLOG_INFO("set_names=%d verbosity=%d names=%d", set_names,
1762 dpctl_p.verbosity, dpctl_p.names);
1763
1764 if (!error) {
1765 dpctl_command_handler *handler = (dpctl_command_handler *) aux;
1766 error = handler(argc, argv, &dpctl_p) != 0;
1767 }
1768
1769 if (error) {
1770 unixctl_command_reply_error(conn, ds_cstr(&ds));
1771 } else {
1772 unixctl_command_reply(conn, ds_cstr(&ds));
1773 }
1774
1775 ds_destroy(&ds);
1776 }
1777
1778 void
1779 dpctl_unixctl_register(void)
1780 {
1781 const struct dpctl_command *p;
1782
1783 for (p = all_commands; p->name != NULL; p++) {
1784 if (strcmp(p->name, "help")) {
1785 char *cmd_name = xasprintf("dpctl/%s", p->name);
1786 unixctl_command_register(cmd_name,
1787 p->usage,
1788 p->min_args,
1789 p->max_args,
1790 dpctl_unixctl_handler,
1791 p->handler);
1792 free(cmd_name);
1793 }
1794 }
1795 }