2 * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira Networks.
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:
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 #include <sys/socket.h>
27 #include <sys/fcntl.h>
31 #include "byte-order.h"
32 #include "classifier.h"
33 #include "command-line.h"
37 #include "dynamic-string.h"
41 #include "ofp-errors.h"
42 #include "ofp-parse.h"
43 #include "ofp-print.h"
46 #include "ofproto/ofproto.h"
47 #include "openflow/nicira-ext.h"
48 #include "openflow/openflow.h"
50 #include "poll-loop.h"
52 #include "stream-ssl.h"
59 VLOG_DEFINE_THIS_MODULE(ofctl
);
61 /* --strict: Use strict matching for flow mod commands? Additionally governs
62 * use of nx_pull_match() instead of nx_pull_match_loose() in parse-nx-match.
66 /* --readd: If true, on replace-flows, re-add even flows that have not changed
67 * (to reset flow counters). */
70 /* -F, --flow-format: Flow format to use. Either one of NXFF_* to force a
71 * particular flow format or -1 to let ovs-ofctl choose intelligently. */
72 static int preferred_flow_format
= -1;
74 /* -P, --packet-in-format: Packet IN format to use in monitor and snoop
75 * commands. Either one of NXPIF_* to force a particular packet_in format, or
76 * -1 to let ovs-ofctl choose the default. */
77 static int preferred_packet_in_format
= -1;
79 /* -m, --more: Additional verbosity for ofp-print functions. */
82 static const struct command all_commands
[];
84 static void usage(void) NO_RETURN
;
85 static void parse_options(int argc
, char *argv
[]);
88 main(int argc
, char *argv
[])
90 set_program_name(argv
[0]);
91 parse_options(argc
, argv
);
92 signal(SIGPIPE
, SIG_IGN
);
93 run_command(argc
- optind
, argv
+ optind
, all_commands
);
98 parse_options(int argc
, char *argv
[])
101 OPT_STRICT
= UCHAR_MAX
+ 1,
106 static struct option long_options
[] = {
107 {"timeout", required_argument
, NULL
, 't'},
108 {"strict", no_argument
, NULL
, OPT_STRICT
},
109 {"readd", no_argument
, NULL
, OPT_READD
},
110 {"flow-format", required_argument
, NULL
, 'F'},
111 {"packet-in-format", required_argument
, NULL
, 'P'},
112 {"more", no_argument
, NULL
, 'm'},
113 {"help", no_argument
, NULL
, 'h'},
114 {"version", no_argument
, NULL
, 'V'},
117 STREAM_SSL_LONG_OPTIONS
,
120 char *short_options
= long_options_to_short_options(long_options
);
123 unsigned long int timeout
;
126 c
= getopt_long(argc
, argv
, short_options
, long_options
, NULL
);
133 timeout
= strtoul(optarg
, NULL
, 10);
135 ovs_fatal(0, "value %s on -t or --timeout is not at least 1",
143 preferred_flow_format
= ofputil_flow_format_from_string(optarg
);
144 if (preferred_flow_format
< 0) {
145 ovs_fatal(0, "unknown flow format `%s'", optarg
);
150 preferred_packet_in_format
=
151 ofputil_packet_in_format_from_string(optarg
);
152 if (preferred_packet_in_format
< 0) {
153 ovs_fatal(0, "unknown packet-in format `%s'", optarg
);
165 ovs_print_version(OFP_VERSION
, OFP_VERSION
);
176 DAEMON_OPTION_HANDLERS
178 STREAM_SSL_OPTION_HANDLERS
193 printf("%s: OpenFlow switch management utility\n"
194 "usage: %s [OPTIONS] COMMAND [ARG...]\n"
195 "\nFor OpenFlow switches:\n"
196 " show SWITCH show OpenFlow information\n"
197 " dump-desc SWITCH print switch description\n"
198 " dump-tables SWITCH print table stats\n"
199 " mod-port SWITCH IFACE ACT modify port behavior\n"
200 " get-frags SWITCH print fragment handling behavior\n"
201 " set-frags SWITCH FRAG_MODE set fragment handling behavior\n"
202 " dump-ports SWITCH [PORT] print port statistics\n"
203 " dump-flows SWITCH print all flow entries\n"
204 " dump-flows SWITCH FLOW print matching FLOWs\n"
205 " dump-aggregate SWITCH print aggregate flow statistics\n"
206 " dump-aggregate SWITCH FLOW print aggregate stats for FLOWs\n"
207 " queue-stats SWITCH [PORT [QUEUE]] dump queue stats\n"
208 " add-flow SWITCH FLOW add flow described by FLOW\n"
209 " add-flows SWITCH FILE add flows from FILE\n"
210 " mod-flows SWITCH FLOW modify actions of matching FLOWs\n"
211 " del-flows SWITCH [FLOW] delete matching FLOWs\n"
212 " replace-flows SWITCH FILE replace flows with those in FILE\n"
213 " diff-flows SOURCE1 SOURCE2 compare flows from two sources\n"
214 " packet-out SWITCH IN_PORT ACTIONS PACKET...\n"
215 " execute ACTIONS on PACKET\n"
216 " monitor SWITCH [MISSLEN] [invalid_ttl]\n"
217 " print packets received from SWITCH\n"
218 " snoop SWITCH snoop on SWITCH and its controller\n"
219 "\nFor OpenFlow switches and controllers:\n"
220 " probe TARGET probe whether TARGET is up\n"
221 " ping TARGET [N] latency of N-byte echos\n"
222 " benchmark TARGET N COUNT bandwidth of COUNT N-byte echos\n"
223 "where SWITCH or TARGET is an active OpenFlow connection method.\n",
224 program_name
, program_name
);
225 vconn_usage(true, false, false);
228 printf("\nOther options:\n"
229 " --strict use strict match for flow commands\n"
230 " --readd replace flows that haven't changed\n"
231 " -F, --flow-format=FORMAT force particular flow format\n"
232 " -P, --packet-in-format=FRMT force particular packet in format\n"
233 " -m, --more be more verbose printing OpenFlow\n"
234 " -t, --timeout=SECS give up after SECS seconds\n"
235 " -h, --help display this help message\n"
236 " -V, --version display version information\n");
241 ofctl_exit(struct unixctl_conn
*conn
, int argc OVS_UNUSED
,
242 const char *argv
[] OVS_UNUSED
, void *exiting_
)
244 bool *exiting
= exiting_
;
246 unixctl_command_reply(conn
, 200, "");
249 static void run(int retval
, const char *message
, ...)
252 static void run(int retval
, const char *message
, ...)
257 va_start(args
, message
);
258 ovs_fatal_valist(retval
, message
, args
);
262 /* Generic commands. */
265 open_vconn_socket(const char *name
, struct vconn
**vconnp
)
267 char *vconn_name
= xasprintf("unix:%s", name
);
268 VLOG_DBG("connecting to %s", vconn_name
);
269 run(vconn_open_block(vconn_name
, OFP_VERSION
, vconnp
),
270 "connecting to %s", vconn_name
);
275 open_vconn__(const char *name
, const char *default_suffix
,
276 struct vconn
**vconnp
)
278 char *datapath_name
, *datapath_type
, *socket_name
;
282 bridge_path
= xasprintf("%s/%s.%s", ovs_rundir(), name
, default_suffix
);
284 ofproto_parse_name(name
, &datapath_name
, &datapath_type
);
285 socket_name
= xasprintf("%s/%s.%s",
286 ovs_rundir(), datapath_name
, default_suffix
);
290 if (strchr(name
, ':')) {
291 run(vconn_open_block(name
, OFP_VERSION
, vconnp
),
292 "connecting to %s", name
);
293 } else if (!stat(name
, &s
) && S_ISSOCK(s
.st_mode
)) {
294 open_vconn_socket(name
, vconnp
);
295 } else if (!stat(bridge_path
, &s
) && S_ISSOCK(s
.st_mode
)) {
296 open_vconn_socket(bridge_path
, vconnp
);
297 } else if (!stat(socket_name
, &s
)) {
298 if (!S_ISSOCK(s
.st_mode
)) {
299 ovs_fatal(0, "cannot connect to %s: %s is not a socket",
302 open_vconn_socket(socket_name
, vconnp
);
304 ovs_fatal(0, "%s is not a bridge or a socket", name
);
312 open_vconn(const char *name
, struct vconn
**vconnp
)
314 return open_vconn__(name
, "mgmt", vconnp
);
318 alloc_stats_request(size_t rq_len
, uint16_t type
, struct ofpbuf
**bufferp
)
320 struct ofp_stats_msg
*rq
;
322 rq
= make_openflow(rq_len
, OFPT_STATS_REQUEST
, bufferp
);
323 rq
->type
= htons(type
);
324 rq
->flags
= htons(0);
329 send_openflow_buffer(struct vconn
*vconn
, struct ofpbuf
*buffer
)
331 update_openflow_length(buffer
);
332 run(vconn_send_block(vconn
, buffer
), "failed to send packet to switch");
336 dump_transaction(const char *vconn_name
, struct ofpbuf
*request
)
339 struct ofpbuf
*reply
;
341 update_openflow_length(request
);
342 open_vconn(vconn_name
, &vconn
);
343 run(vconn_transact(vconn
, request
, &reply
), "talking to %s", vconn_name
);
344 ofp_print(stdout
, reply
->data
, reply
->size
, verbosity
+ 1);
349 dump_trivial_transaction(const char *vconn_name
, uint8_t request_type
)
351 struct ofpbuf
*request
;
352 make_openflow(sizeof(struct ofp_header
), request_type
, &request
);
353 dump_transaction(vconn_name
, request
);
357 dump_stats_transaction(const char *vconn_name
, struct ofpbuf
*request
)
359 ovs_be32 send_xid
= ((struct ofp_header
*) request
->data
)->xid
;
363 open_vconn(vconn_name
, &vconn
);
364 send_openflow_buffer(vconn
, request
);
367 struct ofpbuf
*reply
;
369 run(vconn_recv_block(vconn
, &reply
), "OpenFlow packet receive failed");
370 recv_xid
= ((struct ofp_header
*) reply
->data
)->xid
;
371 if (send_xid
== recv_xid
) {
372 struct ofp_stats_msg
*osm
;
374 ofp_print(stdout
, reply
->data
, reply
->size
, verbosity
+ 1);
376 osm
= ofpbuf_at(reply
, 0, sizeof *osm
);
377 done
= !osm
|| !(ntohs(osm
->flags
) & OFPSF_REPLY_MORE
);
379 VLOG_DBG("received reply with xid %08"PRIx32
" "
380 "!= expected %08"PRIx32
, recv_xid
, send_xid
);
382 ofpbuf_delete(reply
);
388 dump_trivial_stats_transaction(const char *vconn_name
, uint8_t stats_type
)
390 struct ofpbuf
*request
;
391 alloc_stats_request(sizeof(struct ofp_stats_msg
), stats_type
, &request
);
392 dump_stats_transaction(vconn_name
, request
);
395 /* Sends 'request', which should be a request that only has a reply if an error
396 * occurs, and waits for it to succeed or fail. If an error does occur, prints
397 * it and exits with an error.
399 * Destroys all of the 'requests'. */
401 transact_multiple_noreply(struct vconn
*vconn
, struct list
*requests
)
403 struct ofpbuf
*request
, *reply
;
405 LIST_FOR_EACH (request
, list_node
, requests
) {
406 update_openflow_length(request
);
409 run(vconn_transact_multiple_noreply(vconn
, requests
, &reply
),
410 "talking to %s", vconn_get_name(vconn
));
412 ofp_print(stderr
, reply
->data
, reply
->size
, verbosity
+ 2);
415 ofpbuf_delete(reply
);
418 /* Sends 'request', which should be a request that only has a reply if an error
419 * occurs, and waits for it to succeed or fail. If an error does occur, prints
420 * it and exits with an error.
422 * Destroys 'request'. */
424 transact_noreply(struct vconn
*vconn
, struct ofpbuf
*request
)
426 struct list requests
;
428 list_init(&requests
);
429 list_push_back(&requests
, &request
->list_node
);
430 transact_multiple_noreply(vconn
, &requests
);
434 fetch_switch_config(struct vconn
*vconn
, struct ofp_switch_config
*config_
)
436 struct ofp_switch_config
*config
;
437 struct ofp_header
*header
;
438 struct ofpbuf
*request
;
439 struct ofpbuf
*reply
;
441 make_openflow(sizeof(struct ofp_header
), OFPT_GET_CONFIG_REQUEST
,
443 run(vconn_transact(vconn
, request
, &reply
),
444 "talking to %s", vconn_get_name(vconn
));
446 header
= reply
->data
;
447 if (header
->type
!= OFPT_GET_CONFIG_REPLY
||
448 header
->length
!= htons(sizeof *config
)) {
449 ovs_fatal(0, "%s: bad reply to config request", vconn_get_name(vconn
));
452 config
= reply
->data
;
455 ofpbuf_delete(reply
);
459 set_switch_config(struct vconn
*vconn
, struct ofp_switch_config
*config_
)
461 struct ofp_switch_config
*config
;
462 struct ofp_header save_header
;
463 struct ofpbuf
*request
;
465 config
= make_openflow(sizeof *config
, OFPT_SET_CONFIG
, &request
);
466 save_header
= config
->header
;
468 config
->header
= save_header
;
470 transact_noreply(vconn
, request
);
474 do_show(int argc OVS_UNUSED
, char *argv
[])
476 dump_trivial_transaction(argv
[1], OFPT_FEATURES_REQUEST
);
477 dump_trivial_transaction(argv
[1], OFPT_GET_CONFIG_REQUEST
);
481 do_dump_desc(int argc OVS_UNUSED
, char *argv
[])
483 dump_trivial_stats_transaction(argv
[1], OFPST_DESC
);
487 do_dump_tables(int argc OVS_UNUSED
, char *argv
[])
489 dump_trivial_stats_transaction(argv
[1], OFPST_TABLE
);
492 /* Opens a connection to 'vconn_name', fetches the ofp_phy_port structure for
493 * 'port_name' (which may be a port name or number), and copies it into
496 fetch_ofp_phy_port(const char *vconn_name
, const char *port_name
,
497 struct ofp_phy_port
*oppp
)
499 struct ofpbuf
*request
, *reply
;
500 struct ofp_switch_features
*osf
;
501 unsigned int port_no
;
506 /* Try to interpret the argument as a port number. */
507 if (!str_to_uint(port_name
, 10, &port_no
)) {
511 /* Fetch the switch's ofp_switch_features. */
512 make_openflow(sizeof(struct ofp_header
), OFPT_FEATURES_REQUEST
, &request
);
513 open_vconn(vconn_name
, &vconn
);
514 run(vconn_transact(vconn
, request
, &reply
), "talking to %s", vconn_name
);
517 if (reply
->size
< sizeof *osf
) {
518 ovs_fatal(0, "%s: received too-short features reply (only %zu bytes)",
519 vconn_name
, reply
->size
);
521 n_ports
= (reply
->size
- sizeof *osf
) / sizeof *osf
->ports
;
523 for (port_idx
= 0; port_idx
< n_ports
; port_idx
++) {
524 const struct ofp_phy_port
*opp
= &osf
->ports
[port_idx
];
526 if (port_no
!= UINT_MAX
527 ? htons(port_no
) == opp
->port_no
528 : !strncmp(opp
->name
, port_name
, sizeof opp
->name
)) {
530 ofpbuf_delete(reply
);
535 ovs_fatal(0, "%s: couldn't find port `%s'", vconn_name
, port_name
);
538 /* Returns the port number corresponding to 'port_name' (which may be a port
539 * name or number) within the switch 'vconn_name'. */
541 str_to_port_no(const char *vconn_name
, const char *port_name
)
543 unsigned int port_no
;
545 if (str_to_uint(port_name
, 10, &port_no
)) {
548 struct ofp_phy_port opp
;
550 fetch_ofp_phy_port(vconn_name
, port_name
, &opp
);
551 return ntohs(opp
.port_no
);
556 try_set_flow_format(struct vconn
*vconn
, enum nx_flow_format flow_format
)
558 struct ofpbuf
*sff
, *reply
;
560 sff
= ofputil_make_set_flow_format(flow_format
);
561 run(vconn_transact_noreply(vconn
, sff
, &reply
),
562 "talking to %s", vconn_get_name(vconn
));
564 char *s
= ofp_to_string(reply
->data
, reply
->size
, 2);
565 VLOG_DBG("%s: failed to set flow format %s, controller replied: %s",
566 vconn_get_name(vconn
),
567 ofputil_flow_format_to_string(flow_format
),
570 ofpbuf_delete(reply
);
577 set_flow_format(struct vconn
*vconn
, enum nx_flow_format flow_format
)
579 struct ofpbuf
*sff
= ofputil_make_set_flow_format(flow_format
);
580 transact_noreply(vconn
, sff
);
581 VLOG_DBG("%s: using user-specified flow format %s",
582 vconn_get_name(vconn
),
583 ofputil_flow_format_to_string(flow_format
));
586 static enum nx_flow_format
587 negotiate_highest_flow_format(struct vconn
*vconn
,
588 enum nx_flow_format min_format
)
590 if (preferred_flow_format
!= -1) {
591 if (preferred_flow_format
< min_format
) {
592 ovs_fatal(0, "%s: cannot use requested flow format %s for "
593 "specified flow", vconn_get_name(vconn
),
594 ofputil_flow_format_to_string(min_format
));
597 set_flow_format(vconn
, preferred_flow_format
);
598 return preferred_flow_format
;
600 enum nx_flow_format flow_format
;
602 if (try_set_flow_format(vconn
, NXFF_NXM
)) {
603 flow_format
= NXFF_NXM
;
605 flow_format
= NXFF_OPENFLOW10
;
608 if (flow_format
< min_format
) {
609 ovs_fatal(0, "%s: cannot use switch's most advanced flow format "
610 "%s for specified flow", vconn_get_name(vconn
),
611 ofputil_flow_format_to_string(min_format
));
614 VLOG_DBG("%s: negotiated flow format %s", vconn_get_name(vconn
),
615 ofputil_flow_format_to_string(flow_format
));
621 do_dump_flows__(int argc
, char *argv
[], bool aggregate
)
623 enum nx_flow_format min_flow_format
, flow_format
;
624 struct ofputil_flow_stats_request fsr
;
625 struct ofpbuf
*request
;
628 parse_ofp_flow_stats_request_str(&fsr
, aggregate
, argc
> 2 ? argv
[2] : "");
630 open_vconn(argv
[1], &vconn
);
631 min_flow_format
= ofputil_min_flow_format(&fsr
.match
);
632 if (fsr
.cookie_mask
!= htonll(0)) {
633 min_flow_format
= NXFF_NXM
;
635 flow_format
= negotiate_highest_flow_format(vconn
, min_flow_format
);
636 request
= ofputil_encode_flow_stats_request(&fsr
, flow_format
);
637 dump_stats_transaction(argv
[1], request
);
642 do_dump_flows(int argc
, char *argv
[])
644 return do_dump_flows__(argc
, argv
, false);
648 do_dump_aggregate(int argc
, char *argv
[])
650 return do_dump_flows__(argc
, argv
, true);
654 do_queue_stats(int argc
, char *argv
[])
656 struct ofp_queue_stats_request
*req
;
657 struct ofpbuf
*request
;
659 req
= alloc_stats_request(sizeof *req
, OFPST_QUEUE
, &request
);
661 if (argc
> 2 && argv
[2][0] && strcasecmp(argv
[2], "all")) {
662 req
->port_no
= htons(str_to_port_no(argv
[1], argv
[2]));
664 req
->port_no
= htons(OFPP_ALL
);
666 if (argc
> 3 && argv
[3][0] && strcasecmp(argv
[3], "all")) {
667 req
->queue_id
= htonl(atoi(argv
[3]));
669 req
->queue_id
= htonl(OFPQ_ALL
);
672 memset(req
->pad
, 0, sizeof req
->pad
);
674 dump_stats_transaction(argv
[1], request
);
677 /* Sets up the flow format for a vconn that will be used to modify the flow
678 * table. Returns the flow format used, after possibly adding an OpenFlow
679 * request to 'requests'.
681 * If 'preferred_flow_format' is -1, returns NXFF_OPENFLOW10 without modifying
682 * 'requests', since NXFF_OPENFLOW10 is the default flow format for any
683 * OpenFlow connection.
685 * If 'preferred_flow_format' is a specific format, adds a request to set that
686 * format to 'requests' and returns the format. */
687 static enum nx_flow_format
688 set_initial_format_for_flow_mod(struct list
*requests
)
690 if (preferred_flow_format
< 0) {
691 return NXFF_OPENFLOW10
;
695 sff
= ofputil_make_set_flow_format(preferred_flow_format
);
696 list_push_back(requests
, &sff
->list_node
);
697 return preferred_flow_format
;
701 /* Checks that 'flow_format' is acceptable as a flow format after a flow_mod
702 * operation, given the global 'preferred_flow_format'. */
704 check_final_format_for_flow_mod(enum nx_flow_format flow_format
)
706 if (preferred_flow_format
>= 0 && flow_format
> preferred_flow_format
) {
707 ovs_fatal(0, "flow cannot be expressed in flow format %s "
708 "(flow format %s or better is required)",
709 ofputil_flow_format_to_string(preferred_flow_format
),
710 ofputil_flow_format_to_string(flow_format
));
715 do_flow_mod_file__(int argc OVS_UNUSED
, char *argv
[], uint16_t command
)
717 enum nx_flow_format flow_format
;
718 bool flow_mod_table_id
;
719 struct list requests
;
723 file
= !strcmp(argv
[2], "-") ? stdin
: fopen(argv
[2], "r");
725 ovs_fatal(errno
, "%s: open", argv
[2]);
728 list_init(&requests
);
729 flow_format
= set_initial_format_for_flow_mod(&requests
);
730 flow_mod_table_id
= false;
732 open_vconn(argv
[1], &vconn
);
733 while (parse_ofp_flow_mod_file(&requests
, &flow_format
, &flow_mod_table_id
,
735 check_final_format_for_flow_mod(flow_format
);
736 transact_multiple_noreply(vconn
, &requests
);
746 do_flow_mod__(int argc
, char *argv
[], uint16_t command
)
748 enum nx_flow_format flow_format
;
749 bool flow_mod_table_id
;
750 struct list requests
;
753 if (argc
> 2 && !strcmp(argv
[2], "-")) {
754 do_flow_mod_file__(argc
, argv
, command
);
758 list_init(&requests
);
759 flow_format
= set_initial_format_for_flow_mod(&requests
);
760 flow_mod_table_id
= false;
762 parse_ofp_flow_mod_str(&requests
, &flow_format
, &flow_mod_table_id
,
763 argc
> 2 ? argv
[2] : "", command
, false);
764 check_final_format_for_flow_mod(flow_format
);
766 open_vconn(argv
[1], &vconn
);
767 transact_multiple_noreply(vconn
, &requests
);
772 do_add_flow(int argc
, char *argv
[])
774 do_flow_mod__(argc
, argv
, OFPFC_ADD
);
778 do_add_flows(int argc
, char *argv
[])
780 do_flow_mod_file__(argc
, argv
, OFPFC_ADD
);
784 do_mod_flows(int argc
, char *argv
[])
786 do_flow_mod__(argc
, argv
, strict
? OFPFC_MODIFY_STRICT
: OFPFC_MODIFY
);
790 do_del_flows(int argc
, char *argv
[])
792 do_flow_mod__(argc
, argv
, strict
? OFPFC_DELETE_STRICT
: OFPFC_DELETE
);
796 set_packet_in_format(struct vconn
*vconn
,
797 enum nx_packet_in_format packet_in_format
)
799 struct ofpbuf
*spif
= ofputil_make_set_packet_in_format(packet_in_format
);
800 transact_noreply(vconn
, spif
);
801 VLOG_DBG("%s: using user-specified packet in format %s",
802 vconn_get_name(vconn
),
803 ofputil_packet_in_format_to_string(packet_in_format
));
807 monitor_set_invalid_ttl_to_controller(struct vconn
*vconn
)
809 struct ofp_switch_config config
;
810 enum ofp_config_flags flags
;
812 fetch_switch_config(vconn
, &config
);
813 flags
= ntohs(config
.flags
);
814 if (!(flags
& OFPC_INVALID_TTL_TO_CONTROLLER
)) {
815 /* Set the invalid ttl config. */
816 flags
|= OFPC_INVALID_TTL_TO_CONTROLLER
;
818 config
.flags
= htons(flags
);
819 set_switch_config(vconn
, &config
);
821 /* Then retrieve the configuration to see if it really took. OpenFlow
822 * doesn't define error reporting for bad modes, so this is all we can
824 fetch_switch_config(vconn
, &config
);
825 flags
= ntohs(config
.flags
);
826 if (!(flags
& OFPC_INVALID_TTL_TO_CONTROLLER
)) {
827 ovs_fatal(0, "setting invalid_ttl_to_controller failed (this "
828 "switch probably doesn't support mode)");
835 /* Converts hex digits in 'hex' to an OpenFlow message in '*msgp'. The
836 * caller must free '*msgp'. On success, returns NULL. On failure, returns
837 * an error message and stores NULL in '*msgp'. */
839 openflow_from_hex(const char *hex
, struct ofpbuf
**msgp
)
841 struct ofp_header
*oh
;
844 msg
= ofpbuf_new(strlen(hex
) / 2);
847 if (ofpbuf_put_hex(msg
, hex
, NULL
)[0] != '\0') {
849 return "Trailing garbage in hex data";
852 if (msg
->size
< sizeof(struct ofp_header
)) {
854 return "Message too short for OpenFlow";
858 if (msg
->size
!= ntohs(oh
->length
)) {
860 return "Message size does not match length in OpenFlow header";
868 ofctl_send(struct unixctl_conn
*conn
, int argc
,
869 const char *argv
[], void *vconn_
)
871 struct vconn
*vconn
= vconn_
;
878 for (i
= 1; i
< argc
; i
++) {
879 const char *error_msg
;
883 error_msg
= openflow_from_hex(argv
[i
], &msg
);
885 ds_put_format(&reply
, "%s\n", error_msg
);
890 fprintf(stderr
, "send: ");
891 ofp_print(stderr
, msg
->data
, msg
->size
, verbosity
);
893 error
= vconn_send_block(vconn
, msg
);
896 ds_put_format(&reply
, "%s\n", strerror(error
));
899 ds_put_cstr(&reply
, "sent\n");
902 unixctl_command_reply(conn
, ok
? 200 : 501, ds_cstr(&reply
));
907 struct vconn
*vconn
; /* OpenFlow connection for sending barrier. */
908 struct unixctl_conn
*conn
; /* Connection waiting for barrier response. */
912 ofctl_barrier(struct unixctl_conn
*conn
, int argc OVS_UNUSED
,
913 const char *argv
[] OVS_UNUSED
, void *aux_
)
915 struct barrier_aux
*aux
= aux_
;
920 unixctl_command_reply(conn
, 501, "already waiting for barrier reply");
924 msg
= ofputil_encode_barrier_request();
925 fprintf(stderr
, "send: ");
926 ofp_print(stderr
, msg
->data
, msg
->size
, verbosity
);
928 error
= vconn_send_block(aux
->vconn
, msg
);
931 unixctl_command_reply(conn
, 501, strerror(error
));
938 ofctl_set_output_file(struct unixctl_conn
*conn
, int argc OVS_UNUSED
,
939 const char *argv
[], void *aux OVS_UNUSED
)
943 fd
= open(argv
[1], O_CREAT
| O_TRUNC
| O_WRONLY
, 0666);
945 unixctl_command_reply(conn
, 501, strerror(errno
));
950 dup2(fd
, STDERR_FILENO
);
952 unixctl_command_reply(conn
, 200, "");
956 monitor_vconn(struct vconn
*vconn
)
958 struct barrier_aux barrier_aux
= { vconn
, NULL
};
959 struct unixctl_server
*server
;
960 bool exiting
= false;
963 daemon_save_fd(STDERR_FILENO
);
965 error
= unixctl_server_create(NULL
, &server
);
967 ovs_fatal(error
, "failed to create unixctl server");
969 unixctl_command_register("exit", "", 0, 0, ofctl_exit
, &exiting
);
970 unixctl_command_register("ofctl/send", "OFMSG...", 1, INT_MAX
,
972 unixctl_command_register("ofctl/barrier", "", 0, 0,
973 ofctl_barrier
, &barrier_aux
);
974 unixctl_command_register("ofctl/set-output-file", "FILE", 1, 1,
975 ofctl_set_output_file
, NULL
);
976 daemonize_complete();
982 unixctl_server_run(server
);
987 retval
= vconn_recv(vconn
, &b
);
988 if (retval
== EAGAIN
) {
991 msg_type
= ((const struct ofp_header
*) b
->data
)->type
;
993 run(retval
, "vconn_recv");
994 ofp_print(stderr
, b
->data
, b
->size
, verbosity
+ 2);
997 if (barrier_aux
.conn
&& msg_type
== OFPT_BARRIER_REPLY
) {
998 unixctl_command_reply(barrier_aux
.conn
, 200, "");
999 barrier_aux
.conn
= NULL
;
1008 vconn_run_wait(vconn
);
1009 vconn_recv_wait(vconn
);
1010 unixctl_server_wait(server
);
1014 unixctl_server_destroy(server
);
1018 do_monitor(int argc
, char *argv
[])
1020 struct vconn
*vconn
;
1022 open_vconn(argv
[1], &vconn
);
1024 struct ofp_switch_config config
;
1026 fetch_switch_config(vconn
, &config
);
1027 config
.miss_send_len
= htons(atoi(argv
[2]));
1028 set_switch_config(vconn
, &config
);
1031 if (!strcmp(argv
[3], "invalid_ttl")) {
1032 monitor_set_invalid_ttl_to_controller(vconn
);
1035 if (preferred_packet_in_format
>= 0) {
1036 set_packet_in_format(vconn
, preferred_packet_in_format
);
1038 struct ofpbuf
*spif
, *reply
;
1040 spif
= ofputil_make_set_packet_in_format(NXPIF_NXM
);
1041 run(vconn_transact_noreply(vconn
, spif
, &reply
),
1042 "talking to %s", vconn_get_name(vconn
));
1044 char *s
= ofp_to_string(reply
->data
, reply
->size
, 2);
1045 VLOG_DBG("%s: failed to set packet in format to nxm, controller"
1046 " replied: %s. Falling back to the switch default.",
1047 vconn_get_name(vconn
), s
);
1049 ofpbuf_delete(reply
);
1053 monitor_vconn(vconn
);
1057 do_snoop(int argc OVS_UNUSED
, char *argv
[])
1059 struct vconn
*vconn
;
1061 open_vconn__(argv
[1], "snoop", &vconn
);
1062 monitor_vconn(vconn
);
1066 do_dump_ports(int argc
, char *argv
[])
1068 struct ofp_port_stats_request
*req
;
1069 struct ofpbuf
*request
;
1072 req
= alloc_stats_request(sizeof *req
, OFPST_PORT
, &request
);
1073 port
= argc
> 2 ? str_to_port_no(argv
[1], argv
[2]) : OFPP_NONE
;
1074 req
->port_no
= htons(port
);
1075 dump_stats_transaction(argv
[1], request
);
1079 do_probe(int argc OVS_UNUSED
, char *argv
[])
1081 struct ofpbuf
*request
;
1082 struct vconn
*vconn
;
1083 struct ofpbuf
*reply
;
1085 make_openflow(sizeof(struct ofp_header
), OFPT_ECHO_REQUEST
, &request
);
1086 open_vconn(argv
[1], &vconn
);
1087 run(vconn_transact(vconn
, request
, &reply
), "talking to %s", argv
[1]);
1088 if (reply
->size
!= sizeof(struct ofp_header
)) {
1089 ovs_fatal(0, "reply does not match request");
1091 ofpbuf_delete(reply
);
1096 do_packet_out(int argc
, char *argv
[])
1098 struct ofputil_packet_out po
;
1099 struct ofpbuf actions
;
1100 struct vconn
*vconn
;
1103 ofpbuf_init(&actions
, sizeof(union ofp_action
));
1104 parse_ofp_actions(argv
[3], &actions
);
1106 po
.buffer_id
= UINT32_MAX
;
1107 po
.in_port
= (!strcasecmp(argv
[2], "none") ? OFPP_NONE
1108 : !strcasecmp(argv
[2], "local") ? OFPP_LOCAL
1109 : str_to_port_no(argv
[1], argv
[2]));
1110 po
.actions
= actions
.data
;
1111 po
.n_actions
= actions
.size
/ sizeof(union ofp_action
);
1113 open_vconn(argv
[1], &vconn
);
1114 for (i
= 4; i
< argc
; i
++) {
1115 struct ofpbuf
*packet
, *opo
;
1116 const char *error_msg
;
1118 error_msg
= eth_from_hex(argv
[i
], &packet
);
1120 ovs_fatal(0, "%s", error_msg
);
1123 po
.packet
= packet
->data
;
1124 po
.packet_len
= packet
->size
;
1125 opo
= ofputil_encode_packet_out(&po
);
1126 transact_noreply(vconn
, opo
);
1127 ofpbuf_delete(packet
);
1133 do_mod_port(int argc OVS_UNUSED
, char *argv
[])
1135 struct ofp_port_mod
*opm
;
1136 struct ofp_phy_port opp
;
1137 struct ofpbuf
*request
;
1138 struct vconn
*vconn
;
1140 fetch_ofp_phy_port(argv
[1], argv
[2], &opp
);
1142 opm
= make_openflow(sizeof(struct ofp_port_mod
), OFPT_PORT_MOD
, &request
);
1143 opm
->port_no
= opp
.port_no
;
1144 memcpy(opm
->hw_addr
, opp
.hw_addr
, sizeof opm
->hw_addr
);
1145 opm
->config
= htonl(0);
1146 opm
->mask
= htonl(0);
1147 opm
->advertise
= htonl(0);
1149 if (!strcasecmp(argv
[3], "up")) {
1150 opm
->mask
|= htonl(OFPPC_PORT_DOWN
);
1151 } else if (!strcasecmp(argv
[3], "down")) {
1152 opm
->mask
|= htonl(OFPPC_PORT_DOWN
);
1153 opm
->config
|= htonl(OFPPC_PORT_DOWN
);
1154 } else if (!strcasecmp(argv
[3], "flood")) {
1155 opm
->mask
|= htonl(OFPPC_NO_FLOOD
);
1156 } else if (!strcasecmp(argv
[3], "noflood")) {
1157 opm
->mask
|= htonl(OFPPC_NO_FLOOD
);
1158 opm
->config
|= htonl(OFPPC_NO_FLOOD
);
1159 } else if (!strcasecmp(argv
[3], "forward")) {
1160 opm
->mask
|= htonl(OFPPC_NO_FWD
);
1161 } else if (!strcasecmp(argv
[3], "noforward")) {
1162 opm
->mask
|= htonl(OFPPC_NO_FWD
);
1163 opm
->config
|= htonl(OFPPC_NO_FWD
);
1165 ovs_fatal(0, "unknown mod-port command '%s'", argv
[3]);
1168 open_vconn(argv
[1], &vconn
);
1169 transact_noreply(vconn
, request
);
1174 do_get_frags(int argc OVS_UNUSED
, char *argv
[])
1176 struct ofp_switch_config config
;
1177 struct vconn
*vconn
;
1179 open_vconn(argv
[1], &vconn
);
1180 fetch_switch_config(vconn
, &config
);
1181 puts(ofputil_frag_handling_to_string(ntohs(config
.flags
)));
1186 do_set_frags(int argc OVS_UNUSED
, char *argv
[])
1188 struct ofp_switch_config config
;
1189 enum ofp_config_flags mode
;
1190 struct vconn
*vconn
;
1193 if (!ofputil_frag_handling_from_string(argv
[2], &mode
)) {
1194 ovs_fatal(0, "%s: unknown fragment handling mode", argv
[2]);
1197 open_vconn(argv
[1], &vconn
);
1198 fetch_switch_config(vconn
, &config
);
1199 flags
= htons(mode
) | (config
.flags
& htons(~OFPC_FRAG_MASK
));
1200 if (flags
!= config
.flags
) {
1201 /* Set the configuration. */
1202 config
.flags
= flags
;
1203 set_switch_config(vconn
, &config
);
1205 /* Then retrieve the configuration to see if it really took. OpenFlow
1206 * doesn't define error reporting for bad modes, so this is all we can
1208 fetch_switch_config(vconn
, &config
);
1209 if (flags
!= config
.flags
) {
1210 ovs_fatal(0, "%s: setting fragment handling mode failed (this "
1211 "switch probably doesn't support mode \"%s\")",
1212 argv
[1], ofputil_frag_handling_to_string(mode
));
1219 do_ping(int argc
, char *argv
[])
1221 size_t max_payload
= 65535 - sizeof(struct ofp_header
);
1222 unsigned int payload
;
1223 struct vconn
*vconn
;
1226 payload
= argc
> 2 ? atoi(argv
[2]) : 64;
1227 if (payload
> max_payload
) {
1228 ovs_fatal(0, "payload must be between 0 and %zu bytes", max_payload
);
1231 open_vconn(argv
[1], &vconn
);
1232 for (i
= 0; i
< 10; i
++) {
1233 struct timeval start
, end
;
1234 struct ofpbuf
*request
, *reply
;
1235 struct ofp_header
*rq_hdr
, *rpy_hdr
;
1237 rq_hdr
= make_openflow(sizeof(struct ofp_header
) + payload
,
1238 OFPT_ECHO_REQUEST
, &request
);
1239 random_bytes(rq_hdr
+ 1, payload
);
1241 xgettimeofday(&start
);
1242 run(vconn_transact(vconn
, ofpbuf_clone(request
), &reply
), "transact");
1243 xgettimeofday(&end
);
1245 rpy_hdr
= reply
->data
;
1246 if (reply
->size
!= request
->size
1247 || memcmp(rpy_hdr
+ 1, rq_hdr
+ 1, payload
)
1248 || rpy_hdr
->xid
!= rq_hdr
->xid
1249 || rpy_hdr
->type
!= OFPT_ECHO_REPLY
) {
1250 printf("Reply does not match request. Request:\n");
1251 ofp_print(stdout
, request
, request
->size
, verbosity
+ 2);
1253 ofp_print(stdout
, reply
, reply
->size
, verbosity
+ 2);
1255 printf("%zu bytes from %s: xid=%08"PRIx32
" time=%.1f ms\n",
1256 reply
->size
- sizeof *rpy_hdr
, argv
[1], ntohl(rpy_hdr
->xid
),
1257 (1000*(double)(end
.tv_sec
- start
.tv_sec
))
1258 + (.001*(end
.tv_usec
- start
.tv_usec
)));
1259 ofpbuf_delete(request
);
1260 ofpbuf_delete(reply
);
1266 do_benchmark(int argc OVS_UNUSED
, char *argv
[])
1268 size_t max_payload
= 65535 - sizeof(struct ofp_header
);
1269 struct timeval start
, end
;
1270 unsigned int payload_size
, message_size
;
1271 struct vconn
*vconn
;
1276 payload_size
= atoi(argv
[2]);
1277 if (payload_size
> max_payload
) {
1278 ovs_fatal(0, "payload must be between 0 and %zu bytes", max_payload
);
1280 message_size
= sizeof(struct ofp_header
) + payload_size
;
1282 count
= atoi(argv
[3]);
1284 printf("Sending %d packets * %u bytes (with header) = %u bytes total\n",
1285 count
, message_size
, count
* message_size
);
1287 open_vconn(argv
[1], &vconn
);
1288 xgettimeofday(&start
);
1289 for (i
= 0; i
< count
; i
++) {
1290 struct ofpbuf
*request
, *reply
;
1291 struct ofp_header
*rq_hdr
;
1293 rq_hdr
= make_openflow(message_size
, OFPT_ECHO_REQUEST
, &request
);
1294 memset(rq_hdr
+ 1, 0, payload_size
);
1295 run(vconn_transact(vconn
, request
, &reply
), "transact");
1296 ofpbuf_delete(reply
);
1298 xgettimeofday(&end
);
1301 duration
= ((1000*(double)(end
.tv_sec
- start
.tv_sec
))
1302 + (.001*(end
.tv_usec
- start
.tv_usec
)));
1303 printf("Finished in %.1f ms (%.0f packets/s) (%.0f bytes/s)\n",
1304 duration
, count
/ (duration
/ 1000.0),
1305 count
* message_size
/ (duration
/ 1000.0));
1309 do_help(int argc OVS_UNUSED
, char *argv
[] OVS_UNUSED
)
1314 /* replace-flows and diff-flows commands. */
1316 /* A flow table entry, possibly with two different versions. */
1318 struct cls_rule rule
; /* Within a "struct classifier". */
1319 struct fte_version
*versions
[2];
1322 /* One version of a Flow Table Entry. */
1323 struct fte_version
{
1325 uint16_t idle_timeout
;
1326 uint16_t hard_timeout
;
1328 union ofp_action
*actions
;
1332 /* Frees 'version' and the data that it owns. */
1334 fte_version_free(struct fte_version
*version
)
1337 free(version
->actions
);
1342 /* Returns true if 'a' and 'b' are the same, false if they differ.
1344 * Ignores differences in 'flags' because there's no way to retrieve flags from
1345 * an OpenFlow switch. We have to assume that they are the same. */
1347 fte_version_equals(const struct fte_version
*a
, const struct fte_version
*b
)
1349 return (a
->cookie
== b
->cookie
1350 && a
->idle_timeout
== b
->idle_timeout
1351 && a
->hard_timeout
== b
->hard_timeout
1352 && a
->n_actions
== b
->n_actions
1353 && !memcmp(a
->actions
, b
->actions
,
1354 a
->n_actions
* sizeof *a
->actions
));
1357 /* Prints 'version' on stdout. Expects the caller to have printed the rule
1358 * associated with the version. */
1360 fte_version_print(const struct fte_version
*version
)
1364 if (version
->cookie
!= htonll(0)) {
1365 printf(" cookie=0x%"PRIx64
, ntohll(version
->cookie
));
1367 if (version
->idle_timeout
!= OFP_FLOW_PERMANENT
) {
1368 printf(" idle_timeout=%"PRIu16
, version
->idle_timeout
);
1370 if (version
->hard_timeout
!= OFP_FLOW_PERMANENT
) {
1371 printf(" hard_timeout=%"PRIu16
, version
->hard_timeout
);
1375 ofp_print_actions(&s
, version
->actions
, version
->n_actions
);
1376 printf(" %s\n", ds_cstr(&s
));
1381 fte_from_cls_rule(const struct cls_rule
*cls_rule
)
1383 return cls_rule
? CONTAINER_OF(cls_rule
, struct fte
, rule
) : NULL
;
1386 /* Frees 'fte' and its versions. */
1388 fte_free(struct fte
*fte
)
1391 fte_version_free(fte
->versions
[0]);
1392 fte_version_free(fte
->versions
[1]);
1397 /* Frees all of the FTEs within 'cls'. */
1399 fte_free_all(struct classifier
*cls
)
1401 struct cls_cursor cursor
;
1402 struct fte
*fte
, *next
;
1404 cls_cursor_init(&cursor
, cls
, NULL
);
1405 CLS_CURSOR_FOR_EACH_SAFE (fte
, next
, rule
, &cursor
) {
1406 classifier_remove(cls
, &fte
->rule
);
1411 /* Searches 'cls' for an FTE matching 'rule', inserting a new one if
1412 * necessary. Sets 'version' as the version of that rule with the given
1413 * 'index', replacing any existing version, if any.
1415 * Takes ownership of 'version'. */
1417 fte_insert(struct classifier
*cls
, const struct cls_rule
*rule
,
1418 struct fte_version
*version
, int index
)
1420 struct fte
*old
, *fte
;
1422 fte
= xzalloc(sizeof *fte
);
1424 fte
->versions
[index
] = version
;
1426 old
= fte_from_cls_rule(classifier_replace(cls
, &fte
->rule
));
1428 fte_version_free(old
->versions
[index
]);
1429 fte
->versions
[!index
] = old
->versions
[!index
];
1434 /* Reads the flows in 'filename' as flow table entries in 'cls' for the version
1435 * with the specified 'index'. Returns the minimum flow format required to
1436 * represent the flows that were read. */
1437 static enum nx_flow_format
1438 read_flows_from_file(const char *filename
, struct classifier
*cls
, int index
)
1440 enum nx_flow_format min_flow_format
;
1444 file
= !strcmp(filename
, "-") ? stdin
: fopen(filename
, "r");
1446 ovs_fatal(errno
, "%s: open", filename
);
1450 min_flow_format
= NXFF_OPENFLOW10
;
1451 while (!ds_get_preprocessed_line(&s
, file
)) {
1452 struct fte_version
*version
;
1453 struct ofputil_flow_mod fm
;
1454 enum nx_flow_format min_ff
;
1456 parse_ofp_str(&fm
, OFPFC_ADD
, ds_cstr(&s
), true);
1458 version
= xmalloc(sizeof *version
);
1459 version
->cookie
= fm
.cookie
;
1460 version
->idle_timeout
= fm
.idle_timeout
;
1461 version
->hard_timeout
= fm
.hard_timeout
;
1462 version
->flags
= fm
.flags
& (OFPFF_SEND_FLOW_REM
| OFPFF_EMERG
);
1463 version
->actions
= fm
.actions
;
1464 version
->n_actions
= fm
.n_actions
;
1466 min_ff
= ofputil_min_flow_format(&fm
.cr
);
1467 min_flow_format
= MAX(min_flow_format
, min_ff
);
1468 check_final_format_for_flow_mod(min_flow_format
);
1470 fte_insert(cls
, &fm
.cr
, version
, index
);
1474 if (file
!= stdin
) {
1478 return min_flow_format
;
1481 /* Reads the OpenFlow flow table from 'vconn', which has currently active flow
1482 * format 'flow_format', and adds them as flow table entries in 'cls' for the
1483 * version with the specified 'index'. */
1485 read_flows_from_switch(struct vconn
*vconn
, enum nx_flow_format flow_format
,
1486 struct classifier
*cls
, int index
)
1488 struct ofputil_flow_stats_request fsr
;
1489 struct ofpbuf
*request
;
1493 fsr
.aggregate
= false;
1494 cls_rule_init_catchall(&fsr
.match
, 0);
1495 fsr
.out_port
= OFPP_NONE
;
1496 fsr
.table_id
= 0xff;
1497 fsr
.cookie
= fsr
.cookie_mask
= htonll(0);
1498 request
= ofputil_encode_flow_stats_request(&fsr
, flow_format
);
1499 send_xid
= ((struct ofp_header
*) request
->data
)->xid
;
1500 send_openflow_buffer(vconn
, request
);
1505 struct ofpbuf
*reply
;
1507 run(vconn_recv_block(vconn
, &reply
), "OpenFlow packet receive failed");
1508 recv_xid
= ((struct ofp_header
*) reply
->data
)->xid
;
1509 if (send_xid
== recv_xid
) {
1510 const struct ofputil_msg_type
*type
;
1511 const struct ofp_stats_msg
*osm
;
1512 enum ofputil_msg_code code
;
1514 ofputil_decode_msg_type(reply
->data
, &type
);
1515 code
= ofputil_msg_type_code(type
);
1516 if (code
!= OFPUTIL_OFPST_FLOW_REPLY
&&
1517 code
!= OFPUTIL_NXST_FLOW_REPLY
) {
1518 ovs_fatal(0, "received bad reply: %s",
1519 ofp_to_string(reply
->data
, reply
->size
,
1524 if (!(osm
->flags
& htons(OFPSF_REPLY_MORE
))) {
1529 struct fte_version
*version
;
1530 struct ofputil_flow_stats fs
;
1533 retval
= ofputil_decode_flow_stats_reply(&fs
, reply
, false);
1535 if (retval
!= EOF
) {
1536 ovs_fatal(0, "parse error in reply");
1541 version
= xmalloc(sizeof *version
);
1542 version
->cookie
= fs
.cookie
;
1543 version
->idle_timeout
= fs
.idle_timeout
;
1544 version
->hard_timeout
= fs
.hard_timeout
;
1546 version
->n_actions
= fs
.n_actions
;
1547 version
->actions
= xmemdup(fs
.actions
,
1548 fs
.n_actions
* sizeof *fs
.actions
);
1550 fte_insert(cls
, &fs
.rule
, version
, index
);
1553 VLOG_DBG("received reply with xid %08"PRIx32
" "
1554 "!= expected %08"PRIx32
, recv_xid
, send_xid
);
1556 ofpbuf_delete(reply
);
1561 fte_make_flow_mod(const struct fte
*fte
, int index
, uint16_t command
,
1562 enum nx_flow_format flow_format
, struct list
*packets
)
1564 const struct fte_version
*version
= fte
->versions
[index
];
1565 struct ofputil_flow_mod fm
;
1569 fm
.cookie
= version
->cookie
;
1571 fm
.command
= command
;
1572 fm
.idle_timeout
= version
->idle_timeout
;
1573 fm
.hard_timeout
= version
->hard_timeout
;
1574 fm
.buffer_id
= UINT32_MAX
;
1575 fm
.out_port
= OFPP_NONE
;
1576 fm
.flags
= version
->flags
;
1577 if (command
== OFPFC_ADD
|| command
== OFPFC_MODIFY
||
1578 command
== OFPFC_MODIFY_STRICT
) {
1579 fm
.actions
= version
->actions
;
1580 fm
.n_actions
= version
->n_actions
;
1586 ofm
= ofputil_encode_flow_mod(&fm
, flow_format
, false);
1587 list_push_back(packets
, &ofm
->list_node
);
1591 do_replace_flows(int argc OVS_UNUSED
, char *argv
[])
1593 enum { FILE_IDX
= 0, SWITCH_IDX
= 1 };
1594 enum nx_flow_format min_flow_format
, flow_format
;
1595 struct cls_cursor cursor
;
1596 struct classifier cls
;
1597 struct list requests
;
1598 struct vconn
*vconn
;
1601 classifier_init(&cls
);
1602 min_flow_format
= read_flows_from_file(argv
[2], &cls
, FILE_IDX
);
1604 open_vconn(argv
[1], &vconn
);
1605 flow_format
= negotiate_highest_flow_format(vconn
, min_flow_format
);
1606 read_flows_from_switch(vconn
, flow_format
, &cls
, SWITCH_IDX
);
1608 list_init(&requests
);
1610 /* Delete flows that exist on the switch but not in the file. */
1611 cls_cursor_init(&cursor
, &cls
, NULL
);
1612 CLS_CURSOR_FOR_EACH (fte
, rule
, &cursor
) {
1613 struct fte_version
*file_ver
= fte
->versions
[FILE_IDX
];
1614 struct fte_version
*sw_ver
= fte
->versions
[SWITCH_IDX
];
1616 if (sw_ver
&& !file_ver
) {
1617 fte_make_flow_mod(fte
, SWITCH_IDX
, OFPFC_DELETE_STRICT
,
1618 flow_format
, &requests
);
1622 /* Add flows that exist in the file but not on the switch.
1623 * Update flows that exist in both places but differ. */
1624 cls_cursor_init(&cursor
, &cls
, NULL
);
1625 CLS_CURSOR_FOR_EACH (fte
, rule
, &cursor
) {
1626 struct fte_version
*file_ver
= fte
->versions
[FILE_IDX
];
1627 struct fte_version
*sw_ver
= fte
->versions
[SWITCH_IDX
];
1630 && (readd
|| !sw_ver
|| !fte_version_equals(sw_ver
, file_ver
))) {
1631 fte_make_flow_mod(fte
, FILE_IDX
, OFPFC_ADD
, flow_format
,
1635 transact_multiple_noreply(vconn
, &requests
);
1642 read_flows_from_source(const char *source
, struct classifier
*cls
, int index
)
1646 if (source
[0] == '/' || source
[0] == '.'
1647 || (!strchr(source
, ':') && !stat(source
, &s
))) {
1648 read_flows_from_file(source
, cls
, index
);
1650 enum nx_flow_format flow_format
;
1651 struct vconn
*vconn
;
1653 open_vconn(source
, &vconn
);
1654 flow_format
= negotiate_highest_flow_format(vconn
, NXFF_OPENFLOW10
);
1655 read_flows_from_switch(vconn
, flow_format
, cls
, index
);
1661 do_diff_flows(int argc OVS_UNUSED
, char *argv
[])
1663 bool differences
= false;
1664 struct cls_cursor cursor
;
1665 struct classifier cls
;
1668 classifier_init(&cls
);
1669 read_flows_from_source(argv
[1], &cls
, 0);
1670 read_flows_from_source(argv
[2], &cls
, 1);
1672 cls_cursor_init(&cursor
, &cls
, NULL
);
1673 CLS_CURSOR_FOR_EACH (fte
, rule
, &cursor
) {
1674 struct fte_version
*a
= fte
->versions
[0];
1675 struct fte_version
*b
= fte
->versions
[1];
1677 if (!a
|| !b
|| !fte_version_equals(a
, b
)) {
1678 char *rule_s
= cls_rule_to_string(&fte
->rule
);
1680 printf("-%s", rule_s
);
1681 fte_version_print(a
);
1684 printf("+%s", rule_s
);
1685 fte_version_print(b
);
1700 /* Undocumented commands for unit testing. */
1703 print_packet_list(struct list
*packets
)
1705 struct ofpbuf
*packet
, *next
;
1707 LIST_FOR_EACH_SAFE (packet
, next
, list_node
, packets
) {
1708 ofp_print(stdout
, packet
->data
, packet
->size
, verbosity
);
1709 list_remove(&packet
->list_node
);
1710 ofpbuf_delete(packet
);
1714 /* "parse-flow FLOW": parses the argument as a flow (like add-flow) and prints
1715 * it back to stdout. */
1717 do_parse_flow(int argc OVS_UNUSED
, char *argv
[])
1719 enum nx_flow_format flow_format
;
1720 bool flow_mod_table_id
;
1721 struct list packets
;
1723 flow_format
= NXFF_OPENFLOW10
;
1724 if (preferred_flow_format
> 0) {
1725 flow_format
= preferred_flow_format
;
1727 flow_mod_table_id
= false;
1729 list_init(&packets
);
1730 parse_ofp_flow_mod_str(&packets
, &flow_format
, &flow_mod_table_id
,
1731 argv
[1], OFPFC_ADD
, false);
1732 print_packet_list(&packets
);
1735 /* "parse-flows FILENAME": reads the named file as a sequence of flows (like
1736 * add-flows) and prints each of the flows back to stdout. */
1738 do_parse_flows(int argc OVS_UNUSED
, char *argv
[])
1740 enum nx_flow_format flow_format
;
1741 bool flow_mod_table_id
;
1742 struct list packets
;
1745 file
= fopen(argv
[1], "r");
1747 ovs_fatal(errno
, "%s: open", argv
[1]);
1750 flow_format
= NXFF_OPENFLOW10
;
1751 if (preferred_flow_format
> 0) {
1752 flow_format
= preferred_flow_format
;
1754 flow_mod_table_id
= false;
1756 list_init(&packets
);
1757 while (parse_ofp_flow_mod_file(&packets
, &flow_format
, &flow_mod_table_id
,
1759 print_packet_list(&packets
);
1764 /* "parse-nx-match": reads a series of nx_match specifications as strings from
1765 * stdin, does some internal fussing with them, and then prints them back as
1766 * strings on stdout. */
1768 do_parse_nx_match(int argc OVS_UNUSED
, char *argv
[] OVS_UNUSED
)
1773 while (!ds_get_line(&in
, stdin
)) {
1774 struct ofpbuf nx_match
;
1775 struct cls_rule rule
;
1776 ovs_be64 cookie
, cookie_mask
;
1781 /* Delete comments, skip blank lines. */
1787 if (strchr(s
, '#')) {
1788 *strchr(s
, '#') = '\0';
1790 if (s
[strspn(s
, " ")] == '\0') {
1795 /* Convert string to nx_match. */
1796 ofpbuf_init(&nx_match
, 0);
1797 match_len
= nx_match_from_string(ds_cstr(&in
), &nx_match
);
1799 /* Convert nx_match to cls_rule. */
1801 error
= nx_pull_match(&nx_match
, match_len
, 0, &rule
,
1802 &cookie
, &cookie_mask
);
1804 error
= nx_pull_match_loose(&nx_match
, match_len
, 0, &rule
,
1805 &cookie
, &cookie_mask
);
1811 /* Convert cls_rule back to nx_match. */
1812 ofpbuf_uninit(&nx_match
);
1813 ofpbuf_init(&nx_match
, 0);
1814 match_len
= nx_put_match(&nx_match
, &rule
, cookie
, cookie_mask
);
1816 /* Convert nx_match to string. */
1817 out
= nx_match_to_string(nx_match
.data
, match_len
);
1821 printf("nx_pull_match() returned error %s\n",
1822 ofperr_get_name(error
));
1825 ofpbuf_uninit(&nx_match
);
1830 /* "ofp-print HEXSTRING [VERBOSITY]": Converts the hex digits in HEXSTRING into
1831 * binary data, interpreting them as an OpenFlow message, and prints the
1832 * OpenFlow message on stdout, at VERBOSITY (level 2 by default). */
1834 do_ofp_print(int argc
, char *argv
[])
1836 struct ofpbuf packet
;
1838 ofpbuf_init(&packet
, strlen(argv
[1]) / 2);
1839 if (ofpbuf_put_hex(&packet
, argv
[1], NULL
)[0] != '\0') {
1840 ovs_fatal(0, "trailing garbage following hex bytes");
1842 ofp_print(stdout
, packet
.data
, packet
.size
, argc
> 2 ? atoi(argv
[2]) : 2);
1843 ofpbuf_uninit(&packet
);
1846 static const struct command all_commands
[] = {
1847 { "show", 1, 1, do_show
},
1848 { "monitor", 1, 3, do_monitor
},
1849 { "snoop", 1, 1, do_snoop
},
1850 { "dump-desc", 1, 1, do_dump_desc
},
1851 { "dump-tables", 1, 1, do_dump_tables
},
1852 { "dump-flows", 1, 2, do_dump_flows
},
1853 { "dump-aggregate", 1, 2, do_dump_aggregate
},
1854 { "queue-stats", 1, 3, do_queue_stats
},
1855 { "add-flow", 2, 2, do_add_flow
},
1856 { "add-flows", 2, 2, do_add_flows
},
1857 { "mod-flows", 2, 2, do_mod_flows
},
1858 { "del-flows", 1, 2, do_del_flows
},
1859 { "replace-flows", 2, 2, do_replace_flows
},
1860 { "diff-flows", 2, 2, do_diff_flows
},
1861 { "packet-out", 4, INT_MAX
, do_packet_out
},
1862 { "dump-ports", 1, 2, do_dump_ports
},
1863 { "mod-port", 3, 3, do_mod_port
},
1864 { "get-frags", 1, 1, do_get_frags
},
1865 { "set-frags", 2, 2, do_set_frags
},
1866 { "probe", 1, 1, do_probe
},
1867 { "ping", 1, 2, do_ping
},
1868 { "benchmark", 3, 3, do_benchmark
},
1869 { "help", 0, INT_MAX
, do_help
},
1871 /* Undocumented commands for testing. */
1872 { "parse-flow", 1, 1, do_parse_flow
},
1873 { "parse-flows", 1, 1, do_parse_flows
},
1874 { "parse-nx-match", 0, 0, do_parse_nx_match
},
1875 { "ofp-print", 1, 2, do_ofp_print
},
1877 { NULL
, 0, 0, NULL
},