2 * Copyright (c) 2008, 2009 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.
18 #include <arpa/inet.h>
23 #include <netinet/in.h>
32 #include "command-line.h"
36 #include "dynamic-string.h"
40 #include "ofp-print.h"
42 #include "openflow/nicira-ext.h"
43 #include "openflow/openflow.h"
46 #include "socket-util.h"
49 #include "vconn-ssl.h"
53 #define THIS_MODULE VLM_ofctl
55 #define DEFAULT_IDLE_TIMEOUT 60
57 #define MOD_PORT_CMD_UP "up"
58 #define MOD_PORT_CMD_DOWN "down"
59 #define MOD_PORT_CMD_FLOOD "flood"
60 #define MOD_PORT_CMD_NOFLOOD "noflood"
63 /* Settings that may be configured by the user. */
65 bool strict
; /* Use strict matching for flow mod commands */
72 void (*handler
)(const struct settings
*, int argc
, char *argv
[]);
75 static struct command all_commands
[];
77 static void usage(void) NO_RETURN
;
78 static void parse_options(int argc
, char *argv
[], struct settings
*);
80 int main(int argc
, char *argv
[])
85 set_program_name(argv
[0]);
88 parse_options(argc
, argv
, &s
);
89 signal(SIGPIPE
, SIG_IGN
);
94 ovs_fatal(0, "missing command name; use --help for help");
96 for (p
= all_commands
; p
->name
!= NULL
; p
++) {
97 if (!strcmp(p
->name
, argv
[0])) {
99 if (n_arg
< p
->min_args
)
100 ovs_fatal(0, "'%s' command requires at least %d arguments",
101 p
->name
, p
->min_args
);
102 else if (n_arg
> p
->max_args
)
103 ovs_fatal(0, "'%s' command takes at most %d arguments",
104 p
->name
, p
->max_args
);
106 p
->handler(&s
, argc
, argv
);
107 if (ferror(stdout
)) {
108 ovs_fatal(0, "write to stdout failed");
110 if (ferror(stderr
)) {
111 ovs_fatal(0, "write to stderr failed");
117 ovs_fatal(0, "unknown command '%s'; use --help for help", argv
[0]);
123 parse_options(int argc
, char *argv
[], struct settings
*s
)
126 OPT_STRICT
= UCHAR_MAX
+ 1
128 static struct option long_options
[] = {
129 {"timeout", required_argument
, 0, 't'},
130 {"verbose", optional_argument
, 0, 'v'},
131 {"strict", no_argument
, 0, OPT_STRICT
},
132 {"help", no_argument
, 0, 'h'},
133 {"version", no_argument
, 0, 'V'},
134 VCONN_SSL_LONG_OPTIONS
137 char *short_options
= long_options_to_short_options(long_options
);
139 /* Set defaults that we can figure out before parsing options. */
143 unsigned long int timeout
;
146 c
= getopt_long(argc
, argv
, short_options
, long_options
, NULL
);
153 timeout
= strtoul(optarg
, NULL
, 10);
155 ovs_fatal(0, "value %s on -t or --timeout is not at least 1",
166 OVS_PRINT_VERSION(OFP_VERSION
, OFP_VERSION
);
170 vlog_set_verbosity(optarg
);
177 VCONN_SSL_OPTION_HANDLERS
192 printf("%s: OpenFlow switch management utility\n"
193 "usage: %s [OPTIONS] COMMAND [ARG...]\n"
194 "\nFor OpenFlow switches:\n"
195 " show SWITCH show OpenFlow information\n"
196 " status SWITCH [KEY] report statistics (about KEY)\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 " dump-ports SWITCH print port statistics\n"
201 " dump-flows SWITCH print all flow entries\n"
202 " dump-flows SWITCH FLOW print matching FLOWs\n"
203 " dump-aggregate SWITCH print aggregate flow statistics\n"
204 " dump-aggregate SWITCH FLOW print aggregate stats for FLOWs\n"
205 " add-flow SWITCH FLOW add flow described by FLOW\n"
206 " add-flows SWITCH FILE add flows from FILE\n"
207 " mod-flows SWITCH FLOW modify actions of matching FLOWs\n"
208 " del-flows SWITCH [FLOW] delete matching FLOWs\n"
209 " monitor SWITCH MISSLEN EXP print packets received from SWITCH\n"
210 " execute SWITCH CMD [ARG...] execute CMD with ARGS on SWITCH\n"
211 "\nFor OpenFlow switches and controllers:\n"
212 " probe VCONN probe whether VCONN is up\n"
213 " ping VCONN [N] latency of N-byte echos\n"
214 " benchmark VCONN N COUNT bandwidth of COUNT N-byte echos\n"
215 "where each SWITCH is an active OpenFlow connection method.\n",
216 program_name
, program_name
);
217 vconn_usage(true, false, false);
219 printf("\nOther options:\n"
220 " --strict use strict match for flow commands\n"
221 " -t, --timeout=SECS give up after SECS seconds\n"
222 " -h, --help display this help message\n"
223 " -V, --version display version information\n");
227 static void run(int retval
, const char *message
, ...)
230 static void run(int retval
, const char *message
, ...)
235 fprintf(stderr
, "%s: ", program_name
);
236 va_start(args
, message
);
237 vfprintf(stderr
, message
, args
);
240 fputs(": unexpected end of file\n", stderr
);
242 fprintf(stderr
, ": %s\n", strerror(retval
));
249 /* Generic commands. */
252 open_vconn(const char *name
, struct vconn
**vconnp
)
257 if (strstr(name
, ":")) {
258 run(vconn_open_block(name
, OFP_VERSION
, vconnp
),
259 "connecting to %s", name
);
260 } else if (!stat(name
, &s
) && S_ISSOCK(s
.st_mode
)) {
261 char *vconn_name
= xasprintf("unix:%s", name
);
262 VLOG_INFO("connecting to %s", vconn_name
);
263 run(vconn_open_block(vconn_name
, OFP_VERSION
, vconnp
),
264 "connecting to %s", vconn_name
);
266 } else if (!dpif_open(name
, &dpif
)) {
267 char dpif_name
[IF_NAMESIZE
+ 1];
271 run(dpif_port_get_name(&dpif
, ODPP_LOCAL
, dpif_name
, sizeof dpif_name
),
272 "obtaining name of %s", dpif_name
);
274 if (strcmp(dpif_name
, name
)) {
275 VLOG_INFO("datapath %s is named %s", name
, dpif_name
);
278 socket_name
= xasprintf("%s/%s.mgmt", ovs_rundir
, dpif_name
);
279 if (stat(socket_name
, &s
)) {
280 ovs_fatal(errno
, "cannot connect to %s: stat failed on %s",
282 } else if (!S_ISSOCK(s
.st_mode
)) {
283 ovs_fatal(0, "cannot connect to %s: %s is not a socket",
287 vconn_name
= xasprintf("unix:%s", socket_name
);
288 VLOG_INFO("connecting to %s", vconn_name
);
289 run(vconn_open_block(vconn_name
, OFP_VERSION
, vconnp
),
290 "connecting to %s", vconn_name
);
294 ovs_fatal(0, "%s is not a valid connection method", name
);
299 alloc_stats_request(size_t body_len
, uint16_t type
, struct ofpbuf
**bufferp
)
301 struct ofp_stats_request
*rq
;
302 rq
= make_openflow((offsetof(struct ofp_stats_request
, body
)
303 + body_len
), OFPT_STATS_REQUEST
, bufferp
);
304 rq
->type
= htons(type
);
305 rq
->flags
= htons(0);
310 send_openflow_buffer(struct vconn
*vconn
, struct ofpbuf
*buffer
)
312 update_openflow_length(buffer
);
313 run(vconn_send_block(vconn
, buffer
), "failed to send packet to switch");
317 dump_transaction(const char *vconn_name
, struct ofpbuf
*request
)
320 struct ofpbuf
*reply
;
322 update_openflow_length(request
);
323 open_vconn(vconn_name
, &vconn
);
324 run(vconn_transact(vconn
, request
, &reply
), "talking to %s", vconn_name
);
325 ofp_print(stdout
, reply
->data
, reply
->size
, 1);
330 dump_trivial_transaction(const char *vconn_name
, uint8_t request_type
)
332 struct ofpbuf
*request
;
333 make_openflow(sizeof(struct ofp_header
), request_type
, &request
);
334 dump_transaction(vconn_name
, request
);
338 dump_stats_transaction(const char *vconn_name
, struct ofpbuf
*request
)
340 uint32_t send_xid
= ((struct ofp_header
*) request
->data
)->xid
;
344 open_vconn(vconn_name
, &vconn
);
345 send_openflow_buffer(vconn
, request
);
348 struct ofpbuf
*reply
;
350 run(vconn_recv_block(vconn
, &reply
), "OpenFlow packet receive failed");
351 recv_xid
= ((struct ofp_header
*) reply
->data
)->xid
;
352 if (send_xid
== recv_xid
) {
353 struct ofp_stats_reply
*osr
;
355 ofp_print(stdout
, reply
->data
, reply
->size
, 1);
357 osr
= ofpbuf_at(reply
, 0, sizeof *osr
);
358 done
= !osr
|| !(ntohs(osr
->flags
) & OFPSF_REPLY_MORE
);
360 VLOG_DBG("received reply with xid %08"PRIx32
" "
361 "!= expected %08"PRIx32
, recv_xid
, send_xid
);
363 ofpbuf_delete(reply
);
369 dump_trivial_stats_transaction(const char *vconn_name
, uint8_t stats_type
)
371 struct ofpbuf
*request
;
372 alloc_stats_request(0, stats_type
, &request
);
373 dump_stats_transaction(vconn_name
, request
);
377 do_show(const struct settings
*s UNUSED
, int argc UNUSED
, char *argv
[])
379 dump_trivial_transaction(argv
[1], OFPT_FEATURES_REQUEST
);
380 dump_trivial_transaction(argv
[1], OFPT_GET_CONFIG_REQUEST
);
384 do_status(const struct settings
*s UNUSED
, int argc
, char *argv
[])
386 struct nicira_header
*request
, *reply
;
390 request
= make_openflow(sizeof *request
, OFPT_VENDOR
, &b
);
391 request
->vendor
= htonl(NX_VENDOR_ID
);
392 request
->subtype
= htonl(NXT_STATUS_REQUEST
);
394 ofpbuf_put(b
, argv
[2], strlen(argv
[2]));
395 update_openflow_length(b
);
397 open_vconn(argv
[1], &vconn
);
398 run(vconn_transact(vconn
, b
, &b
), "talking to %s", argv
[1]);
401 if (b
->size
< sizeof *reply
) {
402 ovs_fatal(0, "short reply (%zu bytes)", b
->size
);
405 if (reply
->header
.type
!= OFPT_VENDOR
406 || reply
->vendor
!= ntohl(NX_VENDOR_ID
)
407 || reply
->subtype
!= ntohl(NXT_STATUS_REPLY
)) {
408 ofp_print(stderr
, b
->data
, b
->size
, 2);
409 ovs_fatal(0, "bad reply");
412 fwrite(reply
+ 1, b
->size
- sizeof *reply
, 1, stdout
);
416 do_dump_desc(const struct settings
*s UNUSED
, int argc UNUSED
, char *argv
[])
418 dump_trivial_stats_transaction(argv
[1], OFPST_DESC
);
422 do_dump_tables(const struct settings
*s UNUSED
, int argc UNUSED
, char *argv
[])
424 dump_trivial_stats_transaction(argv
[1], OFPST_TABLE
);
429 str_to_u32(const char *str
)
435 value
= strtoul(str
, &tail
, 0);
436 if (errno
== EINVAL
|| errno
== ERANGE
|| *tail
) {
437 ovs_fatal(0, "invalid numeric format %s", str
);
443 str_to_mac(const char *str
, uint8_t mac
[6])
445 if (sscanf(str
, "%"SCNx8
":%"SCNx8
":%"SCNx8
":%"SCNx8
":%"SCNx8
":%"SCNx8
,
446 &mac
[0], &mac
[1], &mac
[2], &mac
[3], &mac
[4], &mac
[5]) != 6) {
447 ovs_fatal(0, "invalid mac address %s", str
);
452 str_to_ip(const char *str_
, uint32_t *ip
)
454 char *str
= xstrdup(str_
);
455 char *save_ptr
= NULL
;
456 const char *name
, *netmask
;
457 struct in_addr in_addr
;
460 name
= strtok_r(str
, "/", &save_ptr
);
461 retval
= name
? lookup_ip(name
, &in_addr
) : EINVAL
;
463 ovs_fatal(0, "%s: could not convert to IP address", str
);
465 *ip
= in_addr
.s_addr
;
467 netmask
= strtok_r(NULL
, "/", &save_ptr
);
470 if (sscanf(netmask
, "%"SCNu8
".%"SCNu8
".%"SCNu8
".%"SCNu8
,
471 &o
[0], &o
[1], &o
[2], &o
[3]) == 4) {
472 uint32_t nm
= (o
[0] << 24) | (o
[1] << 16) | (o
[2] << 8) | o
[3];
475 /* Find first 1-bit. */
476 for (i
= 0; i
< 32; i
++) {
477 if (nm
& (1u << i
)) {
483 /* Verify that the rest of the bits are 1-bits. */
484 for (; i
< 32; i
++) {
485 if (!(nm
& (1u << i
))) {
486 ovs_fatal(0, "%s: %s is not a valid netmask",
491 int prefix
= atoi(netmask
);
492 if (prefix
<= 0 || prefix
> 32) {
493 ovs_fatal(0, "%s: network prefix bits not between 1 and 32",
496 n_wild
= 32 - prefix
;
507 put_action(struct ofpbuf
*b
, size_t size
, uint16_t type
)
509 struct ofp_action_header
*ah
= ofpbuf_put_zeros(b
, size
);
510 ah
->type
= htons(type
);
511 ah
->len
= htons(size
);
515 static struct ofp_action_output
*
516 put_output_action(struct ofpbuf
*b
, uint16_t port
)
518 struct ofp_action_output
*oao
= put_action(b
, sizeof *oao
, OFPAT_OUTPUT
);
519 oao
->port
= htons(port
);
524 put_dl_addr_action(struct ofpbuf
*b
, uint16_t type
, const char *addr
)
526 struct ofp_action_dl_addr
*oada
= put_action(b
, sizeof *oada
, type
);
527 str_to_mac(addr
, oada
->dl_addr
);
532 parse_port_name(const char *name
, uint16_t *port
)
538 static const struct pair pairs
[] = {
539 #define DEF_PAIR(NAME) {#NAME, OFPP_##NAME}
545 DEF_PAIR(CONTROLLER
),
550 static const int n_pairs
= ARRAY_SIZE(pairs
);
553 for (i
= 0; i
< n_pairs
; i
++) {
554 if (!strcasecmp(name
, pairs
[i
].name
)) {
555 *port
= pairs
[i
].value
;
563 str_to_action(char *str
, struct ofpbuf
*b
)
566 char *saveptr
= NULL
;
570 for (act
= strtok_r(str
, ", \t\r\n", &saveptr
), n_actions
= 0; act
;
571 act
= strtok_r(NULL
, ", \t\r\n", &saveptr
), n_actions
++)
576 ovs_fatal(0, "Drop actions must not be followed by other actions");
579 /* Arguments are separated by colons */
580 arg
= strchr(act
, ':');
586 if (!strcasecmp(act
, "mod_vlan_vid")) {
587 struct ofp_action_vlan_vid
*va
;
588 va
= put_action(b
, sizeof *va
, OFPAT_SET_VLAN_VID
);
589 va
->vlan_vid
= htons(str_to_u32(arg
));
590 } else if (!strcasecmp(act
, "mod_vlan_pcp")) {
591 struct ofp_action_vlan_pcp
*va
;
592 va
= put_action(b
, sizeof *va
, OFPAT_SET_VLAN_PCP
);
593 va
->vlan_pcp
= str_to_u32(arg
);
594 } else if (!strcasecmp(act
, "strip_vlan")) {
595 struct ofp_action_header
*ah
;
596 ah
= put_action(b
, sizeof *ah
, OFPAT_STRIP_VLAN
);
597 ah
->type
= htons(OFPAT_STRIP_VLAN
);
598 } else if (!strcasecmp(act
, "mod_dl_src")) {
599 put_dl_addr_action(b
, OFPAT_SET_DL_SRC
, arg
);
600 } else if (!strcasecmp(act
, "mod_dl_dst")) {
601 put_dl_addr_action(b
, OFPAT_SET_DL_DST
, arg
);
602 } else if (!strcasecmp(act
, "output")) {
603 put_output_action(b
, str_to_u32(arg
));
604 } else if (!strcasecmp(act
, "drop")) {
605 /* A drop action in OpenFlow occurs by just not setting
609 ovs_fatal(0, "Drop actions must not be preceded by other "
612 } else if (!strcasecmp(act
, "CONTROLLER")) {
613 struct ofp_action_output
*oao
;
614 oao
= put_output_action(b
, OFPP_CONTROLLER
);
616 /* Unless a numeric argument is specified, we send the whole
617 * packet to the controller. */
618 if (arg
&& (strspn(act
, "0123456789") == strlen(act
))) {
619 oao
->max_len
= htons(str_to_u32(arg
));
621 } else if (parse_port_name(act
, &port
)) {
622 put_output_action(b
, port
);
623 } else if (strspn(act
, "0123456789") == strlen(act
)) {
624 put_output_action(b
, str_to_u32(act
));
626 ovs_fatal(0, "Unknown action: %s", act
);
638 parse_protocol(const char *name
, const struct protocol
**p_out
)
640 static const struct protocol protocols
[] = {
641 { "ip", ETH_TYPE_IP
, 0 },
642 { "arp", ETH_TYPE_ARP
, 0 },
643 { "icmp", ETH_TYPE_IP
, IP_TYPE_ICMP
},
644 { "tcp", ETH_TYPE_IP
, IP_TYPE_TCP
},
645 { "udp", ETH_TYPE_IP
, IP_TYPE_UDP
},
647 const struct protocol
*p
;
649 for (p
= protocols
; p
< &protocols
[ARRAY_SIZE(protocols
)]; p
++) {
650 if (!strcmp(p
->name
, name
)) {
662 enum { F_U8
, F_U16
, F_MAC
, F_IP
} type
;
663 size_t offset
, shift
;
667 parse_field(const char *name
, const struct field
**f_out
)
669 #define F_OFS(MEMBER) offsetof(struct ofp_match, MEMBER)
670 static const struct field fields
[] = {
671 { "in_port", OFPFW_IN_PORT
, F_U16
, F_OFS(in_port
), 0 },
672 { "dl_vlan", OFPFW_DL_VLAN
, F_U16
, F_OFS(dl_vlan
), 0 },
673 { "dl_src", OFPFW_DL_SRC
, F_MAC
, F_OFS(dl_src
), 0 },
674 { "dl_dst", OFPFW_DL_DST
, F_MAC
, F_OFS(dl_dst
), 0 },
675 { "dl_type", OFPFW_DL_TYPE
, F_U16
, F_OFS(dl_type
), 0 },
676 { "nw_src", OFPFW_NW_SRC_MASK
, F_IP
,
677 F_OFS(nw_src
), OFPFW_NW_SRC_SHIFT
},
678 { "nw_dst", OFPFW_NW_DST_MASK
, F_IP
,
679 F_OFS(nw_dst
), OFPFW_NW_DST_SHIFT
},
680 { "nw_proto", OFPFW_NW_PROTO
, F_U8
, F_OFS(nw_proto
), 0 },
681 { "tp_src", OFPFW_TP_SRC
, F_U16
, F_OFS(tp_src
), 0 },
682 { "tp_dst", OFPFW_TP_DST
, F_U16
, F_OFS(tp_dst
), 0 },
683 { "icmp_type", OFPFW_ICMP_TYPE
, F_U16
, F_OFS(icmp_type
), 0 },
684 { "icmp_code", OFPFW_ICMP_CODE
, F_U16
, F_OFS(icmp_code
), 0 }
686 const struct field
*f
;
688 for (f
= fields
; f
< &fields
[ARRAY_SIZE(fields
)]; f
++) {
689 if (!strcmp(f
->name
, name
)) {
699 str_to_flow(char *string
, struct ofp_match
*match
, struct ofpbuf
*actions
,
700 uint8_t *table_idx
, uint16_t *out_port
, uint16_t *priority
,
701 uint16_t *idle_timeout
, uint16_t *hard_timeout
)
703 char *save_ptr
= NULL
;
711 *out_port
= OFPP_NONE
;
714 *priority
= OFP_DEFAULT_PRIORITY
;
717 *idle_timeout
= DEFAULT_IDLE_TIMEOUT
;
720 *hard_timeout
= OFP_FLOW_PERMANENT
;
723 char *act_str
= strstr(string
, "action");
725 ovs_fatal(0, "must specify an action");
729 act_str
= strchr(act_str
, '=');
731 ovs_fatal(0, "must specify an action");
736 str_to_action(act_str
, actions
);
738 memset(match
, 0, sizeof *match
);
739 wildcards
= OFPFW_ALL
;
740 for (name
= strtok_r(string
, "=, \t\r\n", &save_ptr
); name
;
741 name
= strtok_r(NULL
, "=, \t\r\n", &save_ptr
)) {
742 const struct protocol
*p
;
744 if (parse_protocol(name
, &p
)) {
745 wildcards
&= ~OFPFW_DL_TYPE
;
746 match
->dl_type
= htons(p
->dl_type
);
748 wildcards
&= ~OFPFW_NW_PROTO
;
749 match
->nw_proto
= p
->nw_proto
;
752 const struct field
*f
;
755 value
= strtok_r(NULL
, ", \t\r\n", &save_ptr
);
757 ovs_fatal(0, "field %s missing value", name
);
760 if (table_idx
&& !strcmp(name
, "table")) {
761 *table_idx
= atoi(value
);
762 } else if (out_port
&& !strcmp(name
, "out_port")) {
763 *out_port
= atoi(value
);
764 } else if (priority
&& !strcmp(name
, "priority")) {
765 *priority
= atoi(value
);
766 } else if (idle_timeout
&& !strcmp(name
, "idle_timeout")) {
767 *idle_timeout
= atoi(value
);
768 } else if (hard_timeout
&& !strcmp(name
, "hard_timeout")) {
769 *hard_timeout
= atoi(value
);
770 } else if (parse_field(name
, &f
)) {
771 void *data
= (char *) match
+ f
->offset
;
772 if (!strcmp(value
, "*") || !strcmp(value
, "ANY")) {
773 wildcards
|= f
->wildcard
;
775 wildcards
&= ~f
->wildcard
;
776 if (f
->wildcard
== OFPFW_IN_PORT
777 && parse_port_name(value
, (uint16_t *) data
)) {
779 } else if (f
->type
== F_U8
) {
780 *(uint8_t *) data
= str_to_u32(value
);
781 } else if (f
->type
== F_U16
) {
782 *(uint16_t *) data
= htons(str_to_u32(value
));
783 } else if (f
->type
== F_MAC
) {
784 str_to_mac(value
, data
);
785 } else if (f
->type
== F_IP
) {
786 wildcards
|= str_to_ip(value
, data
) << f
->shift
;
792 ovs_fatal(0, "unknown keyword %s", name
);
796 match
->wildcards
= htonl(wildcards
);
800 do_dump_flows(const struct settings
*s UNUSED
, int argc
, char *argv
[])
802 struct ofp_flow_stats_request
*req
;
804 struct ofpbuf
*request
;
806 req
= alloc_stats_request(sizeof *req
, OFPST_FLOW
, &request
);
807 str_to_flow(argc
> 2 ? argv
[2] : "", &req
->match
, NULL
,
808 &req
->table_id
, &out_port
, NULL
, NULL
, NULL
);
809 memset(&req
->pad
, 0, sizeof req
->pad
);
810 req
->out_port
= htons(out_port
);
812 dump_stats_transaction(argv
[1], request
);
816 do_dump_aggregate(const struct settings
*s UNUSED
, int argc
, char *argv
[])
818 struct ofp_aggregate_stats_request
*req
;
819 struct ofpbuf
*request
;
822 req
= alloc_stats_request(sizeof *req
, OFPST_AGGREGATE
, &request
);
823 str_to_flow(argc
> 2 ? argv
[2] : "", &req
->match
, NULL
,
824 &req
->table_id
, &out_port
, NULL
, NULL
, NULL
);
825 memset(&req
->pad
, 0, sizeof req
->pad
);
826 req
->out_port
= htons(out_port
);
828 dump_stats_transaction(argv
[1], request
);
832 do_add_flow(const struct settings
*s UNUSED
, int argc UNUSED
, char *argv
[])
835 struct ofpbuf
*buffer
;
836 struct ofp_flow_mod
*ofm
;
837 uint16_t priority
, idle_timeout
, hard_timeout
;
838 struct ofp_match match
;
840 /* Parse and send. str_to_flow() will expand and reallocate the data in
841 * 'buffer', so we can't keep pointers to across the str_to_flow() call. */
842 make_openflow(sizeof *ofm
, OFPT_FLOW_MOD
, &buffer
);
843 str_to_flow(argv
[2], &match
, buffer
,
844 NULL
, NULL
, &priority
, &idle_timeout
, &hard_timeout
);
847 ofm
->command
= htons(OFPFC_ADD
);
848 ofm
->idle_timeout
= htons(idle_timeout
);
849 ofm
->hard_timeout
= htons(hard_timeout
);
850 ofm
->buffer_id
= htonl(UINT32_MAX
);
851 ofm
->priority
= htons(priority
);
852 ofm
->reserved
= htonl(0);
854 open_vconn(argv
[1], &vconn
);
855 send_openflow_buffer(vconn
, buffer
);
860 do_add_flows(const struct settings
*s UNUSED
, int argc UNUSED
, char *argv
[])
866 file
= fopen(argv
[2], "r");
868 ovs_fatal(errno
, "%s: open", argv
[2]);
871 open_vconn(argv
[1], &vconn
);
872 while (fgets(line
, sizeof line
, file
)) {
873 struct ofpbuf
*buffer
;
874 struct ofp_flow_mod
*ofm
;
875 uint16_t priority
, idle_timeout
, hard_timeout
;
876 struct ofp_match match
;
880 /* Delete comments. */
881 comment
= strchr(line
, '#');
886 /* Drop empty lines. */
887 if (line
[strspn(line
, " \t\n")] == '\0') {
891 /* Parse and send. str_to_flow() will expand and reallocate the data
892 * in 'buffer', so we can't keep pointers to across the str_to_flow()
894 ofm
= make_openflow(sizeof *ofm
, OFPT_FLOW_MOD
, &buffer
);
895 str_to_flow(line
, &match
, buffer
,
896 NULL
, NULL
, &priority
, &idle_timeout
, &hard_timeout
);
899 ofm
->command
= htons(OFPFC_ADD
);
900 ofm
->idle_timeout
= htons(idle_timeout
);
901 ofm
->hard_timeout
= htons(hard_timeout
);
902 ofm
->buffer_id
= htonl(UINT32_MAX
);
903 ofm
->priority
= htons(priority
);
904 ofm
->reserved
= htonl(0);
906 send_openflow_buffer(vconn
, buffer
);
913 do_mod_flows(const struct settings
*s
, int argc UNUSED
, char *argv
[])
915 uint16_t priority
, idle_timeout
, hard_timeout
;
917 struct ofpbuf
*buffer
;
918 struct ofp_flow_mod
*ofm
;
920 /* Parse and send. */
921 ofm
= make_openflow(sizeof *ofm
, OFPT_FLOW_MOD
, &buffer
);
922 str_to_flow(argv
[2], &ofm
->match
, buffer
,
923 NULL
, NULL
, &priority
, &idle_timeout
, &hard_timeout
);
925 ofm
->command
= htons(OFPFC_MODIFY_STRICT
);
927 ofm
->command
= htons(OFPFC_MODIFY
);
929 ofm
->idle_timeout
= htons(idle_timeout
);
930 ofm
->hard_timeout
= htons(hard_timeout
);
931 ofm
->buffer_id
= htonl(UINT32_MAX
);
932 ofm
->priority
= htons(priority
);
933 ofm
->reserved
= htonl(0);
935 open_vconn(argv
[1], &vconn
);
936 send_openflow_buffer(vconn
, buffer
);
940 static void do_del_flows(const struct settings
*s
, int argc
, char *argv
[])
945 struct ofpbuf
*buffer
;
946 struct ofp_flow_mod
*ofm
;
948 /* Parse and send. */
949 ofm
= make_openflow(sizeof *ofm
, OFPT_FLOW_MOD
, &buffer
);
950 str_to_flow(argc
> 2 ? argv
[2] : "", &ofm
->match
, NULL
, NULL
,
951 &out_port
, &priority
, NULL
, NULL
);
953 ofm
->command
= htons(OFPFC_DELETE_STRICT
);
955 ofm
->command
= htons(OFPFC_DELETE
);
957 ofm
->idle_timeout
= htons(0);
958 ofm
->hard_timeout
= htons(0);
959 ofm
->buffer_id
= htonl(UINT32_MAX
);
960 ofm
->out_port
= htons(out_port
);
961 ofm
->priority
= htons(priority
);
962 ofm
->reserved
= htonl(0);
964 open_vconn(argv
[1], &vconn
);
965 send_openflow_buffer(vconn
, buffer
);
970 do_monitor(const struct settings
*s UNUSED
, int argc UNUSED
, char *argv
[])
974 open_vconn(argv
[1], &vconn
);
976 int miss_send_len
= atoi(argv
[2]);
977 int send_flow_exp
= argc
> 3 ? atoi(argv
[3]) : 0;
978 struct ofp_switch_config
*osc
;
981 osc
= make_openflow(sizeof *osc
, OFPT_SET_CONFIG
, &buf
);
982 osc
->flags
= htons(send_flow_exp
? OFPC_SEND_FLOW_EXP
: 0);
983 osc
->miss_send_len
= htons(miss_send_len
);
984 send_openflow_buffer(vconn
, buf
);
988 run(vconn_recv_block(vconn
, &b
), "vconn_recv");
989 ofp_print(stderr
, b
->data
, b
->size
, 2);
995 do_dump_ports(const struct settings
*s UNUSED
, int argc UNUSED
, char *argv
[])
997 dump_trivial_stats_transaction(argv
[1], OFPST_PORT
);
1001 do_probe(const struct settings
*s UNUSED
, int argc UNUSED
, char *argv
[])
1003 struct ofpbuf
*request
;
1004 struct vconn
*vconn
;
1005 struct ofpbuf
*reply
;
1007 make_openflow(sizeof(struct ofp_header
), OFPT_ECHO_REQUEST
, &request
);
1008 open_vconn(argv
[1], &vconn
);
1009 run(vconn_transact(vconn
, request
, &reply
), "talking to %s", argv
[1]);
1010 if (reply
->size
!= sizeof(struct ofp_header
)) {
1011 ovs_fatal(0, "reply does not match request");
1013 ofpbuf_delete(reply
);
1018 do_mod_port(const struct settings
*s UNUSED
, int argc UNUSED
, char *argv
[])
1020 struct ofpbuf
*request
, *reply
;
1021 struct ofp_switch_features
*osf
;
1022 struct ofp_port_mod
*opm
;
1023 struct vconn
*vconn
;
1030 /* Check if the argument is a port index. Otherwise, treat it as
1032 port_no
= strtol(argv
[2], &endptr
, 10);
1033 if (port_no
== 0 && endptr
== argv
[2]) {
1037 /* Send a "Features Request" to get the information we need in order
1038 * to modify the port. */
1039 make_openflow(sizeof(struct ofp_header
), OFPT_FEATURES_REQUEST
, &request
);
1040 open_vconn(argv
[1], &vconn
);
1041 run(vconn_transact(vconn
, request
, &reply
), "talking to %s", argv
[1]);
1044 n_ports
= (reply
->size
- sizeof *osf
) / sizeof *osf
->ports
;
1046 for (port_idx
= 0; port_idx
< n_ports
; port_idx
++) {
1047 if (port_no
!= -1) {
1048 /* Check argument as a port index */
1049 if (osf
->ports
[port_idx
].port_no
== htons(port_no
)) {
1053 /* Check argument as an interface name */
1054 if (!strncmp((char *)osf
->ports
[port_idx
].name
, argv
[2],
1055 sizeof osf
->ports
[0].name
)) {
1061 if (port_idx
== n_ports
) {
1062 ovs_fatal(0, "couldn't find monitored port: %s", argv
[2]);
1065 opm
= make_openflow(sizeof(struct ofp_port_mod
), OFPT_PORT_MOD
, &request
);
1066 opm
->port_no
= osf
->ports
[port_idx
].port_no
;
1067 memcpy(opm
->hw_addr
, osf
->ports
[port_idx
].hw_addr
, sizeof opm
->hw_addr
);
1068 opm
->config
= htonl(0);
1069 opm
->mask
= htonl(0);
1070 opm
->advertise
= htonl(0);
1072 printf("modifying port: %s\n", osf
->ports
[port_idx
].name
);
1074 if (!strncasecmp(argv
[3], MOD_PORT_CMD_UP
, sizeof MOD_PORT_CMD_UP
)) {
1075 opm
->mask
|= htonl(OFPPC_PORT_DOWN
);
1076 } else if (!strncasecmp(argv
[3], MOD_PORT_CMD_DOWN
,
1077 sizeof MOD_PORT_CMD_DOWN
)) {
1078 opm
->mask
|= htonl(OFPPC_PORT_DOWN
);
1079 opm
->config
|= htonl(OFPPC_PORT_DOWN
);
1080 } else if (!strncasecmp(argv
[3], MOD_PORT_CMD_FLOOD
,
1081 sizeof MOD_PORT_CMD_FLOOD
)) {
1082 opm
->mask
|= htonl(OFPPC_NO_FLOOD
);
1083 } else if (!strncasecmp(argv
[3], MOD_PORT_CMD_NOFLOOD
,
1084 sizeof MOD_PORT_CMD_NOFLOOD
)) {
1085 opm
->mask
|= htonl(OFPPC_NO_FLOOD
);
1086 opm
->config
|= htonl(OFPPC_NO_FLOOD
);
1088 ovs_fatal(0, "unknown mod-port command '%s'", argv
[3]);
1091 send_openflow_buffer(vconn
, request
);
1093 ofpbuf_delete(reply
);
1098 do_ping(const struct settings
*s UNUSED
, int argc
, char *argv
[])
1100 size_t max_payload
= 65535 - sizeof(struct ofp_header
);
1101 unsigned int payload
;
1102 struct vconn
*vconn
;
1105 payload
= argc
> 2 ? atoi(argv
[2]) : 64;
1106 if (payload
> max_payload
) {
1107 ovs_fatal(0, "payload must be between 0 and %zu bytes", max_payload
);
1110 open_vconn(argv
[1], &vconn
);
1111 for (i
= 0; i
< 10; i
++) {
1112 struct timeval start
, end
;
1113 struct ofpbuf
*request
, *reply
;
1114 struct ofp_header
*rq_hdr
, *rpy_hdr
;
1116 rq_hdr
= make_openflow(sizeof(struct ofp_header
) + payload
,
1117 OFPT_ECHO_REQUEST
, &request
);
1118 random_bytes(rq_hdr
+ 1, payload
);
1120 gettimeofday(&start
, NULL
);
1121 run(vconn_transact(vconn
, ofpbuf_clone(request
), &reply
), "transact");
1122 gettimeofday(&end
, NULL
);
1124 rpy_hdr
= reply
->data
;
1125 if (reply
->size
!= request
->size
1126 || memcmp(rpy_hdr
+ 1, rq_hdr
+ 1, payload
)
1127 || rpy_hdr
->xid
!= rq_hdr
->xid
1128 || rpy_hdr
->type
!= OFPT_ECHO_REPLY
) {
1129 printf("Reply does not match request. Request:\n");
1130 ofp_print(stdout
, request
, request
->size
, 2);
1132 ofp_print(stdout
, reply
, reply
->size
, 2);
1134 printf("%d bytes from %s: xid=%08"PRIx32
" time=%.1f ms\n",
1135 reply
->size
- sizeof *rpy_hdr
, argv
[1], rpy_hdr
->xid
,
1136 (1000*(double)(end
.tv_sec
- start
.tv_sec
))
1137 + (.001*(end
.tv_usec
- start
.tv_usec
)));
1138 ofpbuf_delete(request
);
1139 ofpbuf_delete(reply
);
1145 do_benchmark(const struct settings
*s UNUSED
, int argc UNUSED
, char *argv
[])
1147 size_t max_payload
= 65535 - sizeof(struct ofp_header
);
1148 struct timeval start
, end
;
1149 unsigned int payload_size
, message_size
;
1150 struct vconn
*vconn
;
1155 payload_size
= atoi(argv
[2]);
1156 if (payload_size
> max_payload
) {
1157 ovs_fatal(0, "payload must be between 0 and %zu bytes", max_payload
);
1159 message_size
= sizeof(struct ofp_header
) + payload_size
;
1161 count
= atoi(argv
[3]);
1163 printf("Sending %d packets * %u bytes (with header) = %u bytes total\n",
1164 count
, message_size
, count
* message_size
);
1166 open_vconn(argv
[1], &vconn
);
1167 gettimeofday(&start
, NULL
);
1168 for (i
= 0; i
< count
; i
++) {
1169 struct ofpbuf
*request
, *reply
;
1170 struct ofp_header
*rq_hdr
;
1172 rq_hdr
= make_openflow(message_size
, OFPT_ECHO_REQUEST
, &request
);
1173 memset(rq_hdr
+ 1, 0, payload_size
);
1174 run(vconn_transact(vconn
, request
, &reply
), "transact");
1175 ofpbuf_delete(reply
);
1177 gettimeofday(&end
, NULL
);
1180 duration
= ((1000*(double)(end
.tv_sec
- start
.tv_sec
))
1181 + (.001*(end
.tv_usec
- start
.tv_usec
)));
1182 printf("Finished in %.1f ms (%.0f packets/s) (%.0f bytes/s)\n",
1183 duration
, count
/ (duration
/ 1000.0),
1184 count
* message_size
/ (duration
/ 1000.0));
1188 do_execute(const struct settings
*s UNUSED
, int argc
, char *argv
[])
1190 struct vconn
*vconn
;
1191 struct ofpbuf
*request
;
1192 struct nicira_header
*nicira
;
1193 struct nx_command_reply
*ncr
;
1197 nicira
= make_openflow(sizeof *nicira
, OFPT_VENDOR
, &request
);
1198 xid
= nicira
->header
.xid
;
1199 nicira
->vendor
= htonl(NX_VENDOR_ID
);
1200 nicira
->subtype
= htonl(NXT_COMMAND_REQUEST
);
1201 ofpbuf_put(request
, argv
[2], strlen(argv
[2]));
1202 for (i
= 3; i
< argc
; i
++) {
1203 ofpbuf_put_zeros(request
, 1);
1204 ofpbuf_put(request
, argv
[i
], strlen(argv
[i
]));
1206 update_openflow_length(request
);
1208 open_vconn(argv
[1], &vconn
);
1209 run(vconn_send_block(vconn
, request
), "send");
1212 struct ofpbuf
*reply
;
1215 run(vconn_recv_xid(vconn
, xid
, &reply
), "recv_xid");
1216 if (reply
->size
< sizeof *ncr
) {
1217 ovs_fatal(0, "reply is too short (%zu bytes < %zu bytes)",
1218 reply
->size
, sizeof *ncr
);
1221 if (ncr
->nxh
.header
.type
!= OFPT_VENDOR
1222 || ncr
->nxh
.vendor
!= htonl(NX_VENDOR_ID
)
1223 || ncr
->nxh
.subtype
!= htonl(NXT_COMMAND_REPLY
)) {
1224 ovs_fatal(0, "reply is invalid");
1227 status
= ntohl(ncr
->status
);
1228 if (status
& NXT_STATUS_STARTED
) {
1229 /* Wait for a second reply. */
1231 } else if (status
& NXT_STATUS_EXITED
) {
1232 fprintf(stderr
, "process terminated normally with exit code %d",
1233 status
& NXT_STATUS_EXITSTATUS
);
1234 } else if (status
& NXT_STATUS_SIGNALED
) {
1235 fprintf(stderr
, "process terminated by signal %d",
1236 status
& NXT_STATUS_TERMSIG
);
1237 } else if (status
& NXT_STATUS_ERROR
) {
1238 fprintf(stderr
, "error executing command");
1240 fprintf(stderr
, "process terminated for unknown reason");
1242 if (status
& NXT_STATUS_COREDUMP
) {
1243 fprintf(stderr
, " (core dumped)");
1247 fwrite(ncr
+ 1, reply
->size
- sizeof *ncr
, 1, stdout
);
1253 do_help(const struct settings
*s UNUSED
, int argc UNUSED
, char *argv
[] UNUSED
)
1258 static struct command all_commands
[] = {
1259 { "show", 1, 1, do_show
},
1260 { "status", 1, 2, do_status
},
1261 { "monitor", 1, 3, do_monitor
},
1262 { "dump-desc", 1, 1, do_dump_desc
},
1263 { "dump-tables", 1, 1, do_dump_tables
},
1264 { "dump-flows", 1, 2, do_dump_flows
},
1265 { "dump-aggregate", 1, 2, do_dump_aggregate
},
1266 { "add-flow", 2, 2, do_add_flow
},
1267 { "add-flows", 2, 2, do_add_flows
},
1268 { "mod-flows", 2, 2, do_mod_flows
},
1269 { "del-flows", 1, 2, do_del_flows
},
1270 { "dump-ports", 1, 1, do_dump_ports
},
1271 { "mod-port", 3, 3, do_mod_port
},
1272 { "probe", 1, 1, do_probe
},
1273 { "ping", 1, 2, do_ping
},
1274 { "benchmark", 3, 3, do_benchmark
},
1275 { "execute", 2, INT_MAX
, do_execute
},
1276 { "help", 0, INT_MAX
, do_help
},
1277 { NULL
, 0, 0, NULL
},