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 oao
->max_len
= htons(UINT16_MAX
);
623 } else if (parse_port_name(act
, &port
)) {
624 put_output_action(b
, port
);
625 } else if (strspn(act
, "0123456789") == strlen(act
)) {
626 put_output_action(b
, str_to_u32(act
));
628 ovs_fatal(0, "Unknown action: %s", act
);
640 parse_protocol(const char *name
, const struct protocol
**p_out
)
642 static const struct protocol protocols
[] = {
643 { "ip", ETH_TYPE_IP
, 0 },
644 { "arp", ETH_TYPE_ARP
, 0 },
645 { "icmp", ETH_TYPE_IP
, IP_TYPE_ICMP
},
646 { "tcp", ETH_TYPE_IP
, IP_TYPE_TCP
},
647 { "udp", ETH_TYPE_IP
, IP_TYPE_UDP
},
649 const struct protocol
*p
;
651 for (p
= protocols
; p
< &protocols
[ARRAY_SIZE(protocols
)]; p
++) {
652 if (!strcmp(p
->name
, name
)) {
664 enum { F_U8
, F_U16
, F_MAC
, F_IP
} type
;
665 size_t offset
, shift
;
669 parse_field(const char *name
, const struct field
**f_out
)
671 #define F_OFS(MEMBER) offsetof(struct ofp_match, MEMBER)
672 static const struct field fields
[] = {
673 { "in_port", OFPFW_IN_PORT
, F_U16
, F_OFS(in_port
), 0 },
674 { "dl_vlan", OFPFW_DL_VLAN
, F_U16
, F_OFS(dl_vlan
), 0 },
675 { "dl_src", OFPFW_DL_SRC
, F_MAC
, F_OFS(dl_src
), 0 },
676 { "dl_dst", OFPFW_DL_DST
, F_MAC
, F_OFS(dl_dst
), 0 },
677 { "dl_type", OFPFW_DL_TYPE
, F_U16
, F_OFS(dl_type
), 0 },
678 { "nw_src", OFPFW_NW_SRC_MASK
, F_IP
,
679 F_OFS(nw_src
), OFPFW_NW_SRC_SHIFT
},
680 { "nw_dst", OFPFW_NW_DST_MASK
, F_IP
,
681 F_OFS(nw_dst
), OFPFW_NW_DST_SHIFT
},
682 { "nw_proto", OFPFW_NW_PROTO
, F_U8
, F_OFS(nw_proto
), 0 },
683 { "tp_src", OFPFW_TP_SRC
, F_U16
, F_OFS(tp_src
), 0 },
684 { "tp_dst", OFPFW_TP_DST
, F_U16
, F_OFS(tp_dst
), 0 },
685 { "icmp_type", OFPFW_ICMP_TYPE
, F_U16
, F_OFS(icmp_type
), 0 },
686 { "icmp_code", OFPFW_ICMP_CODE
, F_U16
, F_OFS(icmp_code
), 0 }
688 const struct field
*f
;
690 for (f
= fields
; f
< &fields
[ARRAY_SIZE(fields
)]; f
++) {
691 if (!strcmp(f
->name
, name
)) {
701 str_to_flow(char *string
, struct ofp_match
*match
, struct ofpbuf
*actions
,
702 uint8_t *table_idx
, uint16_t *out_port
, uint16_t *priority
,
703 uint16_t *idle_timeout
, uint16_t *hard_timeout
)
705 char *save_ptr
= NULL
;
713 *out_port
= OFPP_NONE
;
716 *priority
= OFP_DEFAULT_PRIORITY
;
719 *idle_timeout
= DEFAULT_IDLE_TIMEOUT
;
722 *hard_timeout
= OFP_FLOW_PERMANENT
;
725 char *act_str
= strstr(string
, "action");
727 ovs_fatal(0, "must specify an action");
731 act_str
= strchr(act_str
, '=');
733 ovs_fatal(0, "must specify an action");
738 str_to_action(act_str
, actions
);
740 memset(match
, 0, sizeof *match
);
741 wildcards
= OFPFW_ALL
;
742 for (name
= strtok_r(string
, "=, \t\r\n", &save_ptr
); name
;
743 name
= strtok_r(NULL
, "=, \t\r\n", &save_ptr
)) {
744 const struct protocol
*p
;
746 if (parse_protocol(name
, &p
)) {
747 wildcards
&= ~OFPFW_DL_TYPE
;
748 match
->dl_type
= htons(p
->dl_type
);
750 wildcards
&= ~OFPFW_NW_PROTO
;
751 match
->nw_proto
= p
->nw_proto
;
754 const struct field
*f
;
757 value
= strtok_r(NULL
, ", \t\r\n", &save_ptr
);
759 ovs_fatal(0, "field %s missing value", name
);
762 if (table_idx
&& !strcmp(name
, "table")) {
763 *table_idx
= atoi(value
);
764 } else if (out_port
&& !strcmp(name
, "out_port")) {
765 *out_port
= atoi(value
);
766 } else if (priority
&& !strcmp(name
, "priority")) {
767 *priority
= atoi(value
);
768 } else if (idle_timeout
&& !strcmp(name
, "idle_timeout")) {
769 *idle_timeout
= atoi(value
);
770 } else if (hard_timeout
&& !strcmp(name
, "hard_timeout")) {
771 *hard_timeout
= atoi(value
);
772 } else if (parse_field(name
, &f
)) {
773 void *data
= (char *) match
+ f
->offset
;
774 if (!strcmp(value
, "*") || !strcmp(value
, "ANY")) {
775 wildcards
|= f
->wildcard
;
777 wildcards
&= ~f
->wildcard
;
778 if (f
->wildcard
== OFPFW_IN_PORT
779 && parse_port_name(value
, (uint16_t *) data
)) {
781 } else if (f
->type
== F_U8
) {
782 *(uint8_t *) data
= str_to_u32(value
);
783 } else if (f
->type
== F_U16
) {
784 *(uint16_t *) data
= htons(str_to_u32(value
));
785 } else if (f
->type
== F_MAC
) {
786 str_to_mac(value
, data
);
787 } else if (f
->type
== F_IP
) {
788 wildcards
|= str_to_ip(value
, data
) << f
->shift
;
794 ovs_fatal(0, "unknown keyword %s", name
);
798 match
->wildcards
= htonl(wildcards
);
802 do_dump_flows(const struct settings
*s UNUSED
, int argc
, char *argv
[])
804 struct ofp_flow_stats_request
*req
;
806 struct ofpbuf
*request
;
808 req
= alloc_stats_request(sizeof *req
, OFPST_FLOW
, &request
);
809 str_to_flow(argc
> 2 ? argv
[2] : "", &req
->match
, NULL
,
810 &req
->table_id
, &out_port
, NULL
, NULL
, NULL
);
811 memset(&req
->pad
, 0, sizeof req
->pad
);
812 req
->out_port
= htons(out_port
);
814 dump_stats_transaction(argv
[1], request
);
818 do_dump_aggregate(const struct settings
*s UNUSED
, int argc
, char *argv
[])
820 struct ofp_aggregate_stats_request
*req
;
821 struct ofpbuf
*request
;
824 req
= alloc_stats_request(sizeof *req
, OFPST_AGGREGATE
, &request
);
825 str_to_flow(argc
> 2 ? argv
[2] : "", &req
->match
, NULL
,
826 &req
->table_id
, &out_port
, NULL
, NULL
, NULL
);
827 memset(&req
->pad
, 0, sizeof req
->pad
);
828 req
->out_port
= htons(out_port
);
830 dump_stats_transaction(argv
[1], request
);
834 do_add_flow(const struct settings
*s UNUSED
, int argc UNUSED
, char *argv
[])
837 struct ofpbuf
*buffer
;
838 struct ofp_flow_mod
*ofm
;
839 uint16_t priority
, idle_timeout
, hard_timeout
;
840 struct ofp_match match
;
842 /* Parse and send. str_to_flow() will expand and reallocate the data in
843 * 'buffer', so we can't keep pointers to across the str_to_flow() call. */
844 make_openflow(sizeof *ofm
, OFPT_FLOW_MOD
, &buffer
);
845 str_to_flow(argv
[2], &match
, buffer
,
846 NULL
, NULL
, &priority
, &idle_timeout
, &hard_timeout
);
849 ofm
->command
= htons(OFPFC_ADD
);
850 ofm
->idle_timeout
= htons(idle_timeout
);
851 ofm
->hard_timeout
= htons(hard_timeout
);
852 ofm
->buffer_id
= htonl(UINT32_MAX
);
853 ofm
->priority
= htons(priority
);
854 ofm
->reserved
= htonl(0);
856 open_vconn(argv
[1], &vconn
);
857 send_openflow_buffer(vconn
, buffer
);
862 do_add_flows(const struct settings
*s UNUSED
, int argc UNUSED
, char *argv
[])
868 file
= fopen(argv
[2], "r");
870 ovs_fatal(errno
, "%s: open", argv
[2]);
873 open_vconn(argv
[1], &vconn
);
874 while (fgets(line
, sizeof line
, file
)) {
875 struct ofpbuf
*buffer
;
876 struct ofp_flow_mod
*ofm
;
877 uint16_t priority
, idle_timeout
, hard_timeout
;
878 struct ofp_match match
;
882 /* Delete comments. */
883 comment
= strchr(line
, '#');
888 /* Drop empty lines. */
889 if (line
[strspn(line
, " \t\n")] == '\0') {
893 /* Parse and send. str_to_flow() will expand and reallocate the data
894 * in 'buffer', so we can't keep pointers to across the str_to_flow()
896 ofm
= make_openflow(sizeof *ofm
, OFPT_FLOW_MOD
, &buffer
);
897 str_to_flow(line
, &match
, buffer
,
898 NULL
, NULL
, &priority
, &idle_timeout
, &hard_timeout
);
901 ofm
->command
= htons(OFPFC_ADD
);
902 ofm
->idle_timeout
= htons(idle_timeout
);
903 ofm
->hard_timeout
= htons(hard_timeout
);
904 ofm
->buffer_id
= htonl(UINT32_MAX
);
905 ofm
->priority
= htons(priority
);
906 ofm
->reserved
= htonl(0);
908 send_openflow_buffer(vconn
, buffer
);
915 do_mod_flows(const struct settings
*s
, int argc UNUSED
, char *argv
[])
917 uint16_t priority
, idle_timeout
, hard_timeout
;
919 struct ofpbuf
*buffer
;
920 struct ofp_flow_mod
*ofm
;
922 /* Parse and send. */
923 ofm
= make_openflow(sizeof *ofm
, OFPT_FLOW_MOD
, &buffer
);
924 str_to_flow(argv
[2], &ofm
->match
, buffer
,
925 NULL
, NULL
, &priority
, &idle_timeout
, &hard_timeout
);
927 ofm
->command
= htons(OFPFC_MODIFY_STRICT
);
929 ofm
->command
= htons(OFPFC_MODIFY
);
931 ofm
->idle_timeout
= htons(idle_timeout
);
932 ofm
->hard_timeout
= htons(hard_timeout
);
933 ofm
->buffer_id
= htonl(UINT32_MAX
);
934 ofm
->priority
= htons(priority
);
935 ofm
->reserved
= htonl(0);
937 open_vconn(argv
[1], &vconn
);
938 send_openflow_buffer(vconn
, buffer
);
942 static void do_del_flows(const struct settings
*s
, int argc
, char *argv
[])
947 struct ofpbuf
*buffer
;
948 struct ofp_flow_mod
*ofm
;
950 /* Parse and send. */
951 ofm
= make_openflow(sizeof *ofm
, OFPT_FLOW_MOD
, &buffer
);
952 str_to_flow(argc
> 2 ? argv
[2] : "", &ofm
->match
, NULL
, NULL
,
953 &out_port
, &priority
, NULL
, NULL
);
955 ofm
->command
= htons(OFPFC_DELETE_STRICT
);
957 ofm
->command
= htons(OFPFC_DELETE
);
959 ofm
->idle_timeout
= htons(0);
960 ofm
->hard_timeout
= htons(0);
961 ofm
->buffer_id
= htonl(UINT32_MAX
);
962 ofm
->out_port
= htons(out_port
);
963 ofm
->priority
= htons(priority
);
964 ofm
->reserved
= htonl(0);
966 open_vconn(argv
[1], &vconn
);
967 send_openflow_buffer(vconn
, buffer
);
972 do_monitor(const struct settings
*s UNUSED
, int argc UNUSED
, char *argv
[])
976 open_vconn(argv
[1], &vconn
);
978 int miss_send_len
= atoi(argv
[2]);
979 int send_flow_exp
= argc
> 3 ? atoi(argv
[3]) : 0;
980 struct ofp_switch_config
*osc
;
983 osc
= make_openflow(sizeof *osc
, OFPT_SET_CONFIG
, &buf
);
984 osc
->flags
= htons(send_flow_exp
? OFPC_SEND_FLOW_EXP
: 0);
985 osc
->miss_send_len
= htons(miss_send_len
);
986 send_openflow_buffer(vconn
, buf
);
990 run(vconn_recv_block(vconn
, &b
), "vconn_recv");
991 ofp_print(stderr
, b
->data
, b
->size
, 2);
997 do_dump_ports(const struct settings
*s UNUSED
, int argc UNUSED
, char *argv
[])
999 dump_trivial_stats_transaction(argv
[1], OFPST_PORT
);
1003 do_probe(const struct settings
*s UNUSED
, int argc UNUSED
, char *argv
[])
1005 struct ofpbuf
*request
;
1006 struct vconn
*vconn
;
1007 struct ofpbuf
*reply
;
1009 make_openflow(sizeof(struct ofp_header
), OFPT_ECHO_REQUEST
, &request
);
1010 open_vconn(argv
[1], &vconn
);
1011 run(vconn_transact(vconn
, request
, &reply
), "talking to %s", argv
[1]);
1012 if (reply
->size
!= sizeof(struct ofp_header
)) {
1013 ovs_fatal(0, "reply does not match request");
1015 ofpbuf_delete(reply
);
1020 do_mod_port(const struct settings
*s UNUSED
, int argc UNUSED
, char *argv
[])
1022 struct ofpbuf
*request
, *reply
;
1023 struct ofp_switch_features
*osf
;
1024 struct ofp_port_mod
*opm
;
1025 struct vconn
*vconn
;
1032 /* Check if the argument is a port index. Otherwise, treat it as
1034 port_no
= strtol(argv
[2], &endptr
, 10);
1035 if (port_no
== 0 && endptr
== argv
[2]) {
1039 /* Send a "Features Request" to get the information we need in order
1040 * to modify the port. */
1041 make_openflow(sizeof(struct ofp_header
), OFPT_FEATURES_REQUEST
, &request
);
1042 open_vconn(argv
[1], &vconn
);
1043 run(vconn_transact(vconn
, request
, &reply
), "talking to %s", argv
[1]);
1046 n_ports
= (reply
->size
- sizeof *osf
) / sizeof *osf
->ports
;
1048 for (port_idx
= 0; port_idx
< n_ports
; port_idx
++) {
1049 if (port_no
!= -1) {
1050 /* Check argument as a port index */
1051 if (osf
->ports
[port_idx
].port_no
== htons(port_no
)) {
1055 /* Check argument as an interface name */
1056 if (!strncmp((char *)osf
->ports
[port_idx
].name
, argv
[2],
1057 sizeof osf
->ports
[0].name
)) {
1063 if (port_idx
== n_ports
) {
1064 ovs_fatal(0, "couldn't find monitored port: %s", argv
[2]);
1067 opm
= make_openflow(sizeof(struct ofp_port_mod
), OFPT_PORT_MOD
, &request
);
1068 opm
->port_no
= osf
->ports
[port_idx
].port_no
;
1069 memcpy(opm
->hw_addr
, osf
->ports
[port_idx
].hw_addr
, sizeof opm
->hw_addr
);
1070 opm
->config
= htonl(0);
1071 opm
->mask
= htonl(0);
1072 opm
->advertise
= htonl(0);
1074 printf("modifying port: %s\n", osf
->ports
[port_idx
].name
);
1076 if (!strncasecmp(argv
[3], MOD_PORT_CMD_UP
, sizeof MOD_PORT_CMD_UP
)) {
1077 opm
->mask
|= htonl(OFPPC_PORT_DOWN
);
1078 } else if (!strncasecmp(argv
[3], MOD_PORT_CMD_DOWN
,
1079 sizeof MOD_PORT_CMD_DOWN
)) {
1080 opm
->mask
|= htonl(OFPPC_PORT_DOWN
);
1081 opm
->config
|= htonl(OFPPC_PORT_DOWN
);
1082 } else if (!strncasecmp(argv
[3], MOD_PORT_CMD_FLOOD
,
1083 sizeof MOD_PORT_CMD_FLOOD
)) {
1084 opm
->mask
|= htonl(OFPPC_NO_FLOOD
);
1085 } else if (!strncasecmp(argv
[3], MOD_PORT_CMD_NOFLOOD
,
1086 sizeof MOD_PORT_CMD_NOFLOOD
)) {
1087 opm
->mask
|= htonl(OFPPC_NO_FLOOD
);
1088 opm
->config
|= htonl(OFPPC_NO_FLOOD
);
1090 ovs_fatal(0, "unknown mod-port command '%s'", argv
[3]);
1093 send_openflow_buffer(vconn
, request
);
1095 ofpbuf_delete(reply
);
1100 do_ping(const struct settings
*s UNUSED
, int argc
, char *argv
[])
1102 size_t max_payload
= 65535 - sizeof(struct ofp_header
);
1103 unsigned int payload
;
1104 struct vconn
*vconn
;
1107 payload
= argc
> 2 ? atoi(argv
[2]) : 64;
1108 if (payload
> max_payload
) {
1109 ovs_fatal(0, "payload must be between 0 and %zu bytes", max_payload
);
1112 open_vconn(argv
[1], &vconn
);
1113 for (i
= 0; i
< 10; i
++) {
1114 struct timeval start
, end
;
1115 struct ofpbuf
*request
, *reply
;
1116 struct ofp_header
*rq_hdr
, *rpy_hdr
;
1118 rq_hdr
= make_openflow(sizeof(struct ofp_header
) + payload
,
1119 OFPT_ECHO_REQUEST
, &request
);
1120 random_bytes(rq_hdr
+ 1, payload
);
1122 gettimeofday(&start
, NULL
);
1123 run(vconn_transact(vconn
, ofpbuf_clone(request
), &reply
), "transact");
1124 gettimeofday(&end
, NULL
);
1126 rpy_hdr
= reply
->data
;
1127 if (reply
->size
!= request
->size
1128 || memcmp(rpy_hdr
+ 1, rq_hdr
+ 1, payload
)
1129 || rpy_hdr
->xid
!= rq_hdr
->xid
1130 || rpy_hdr
->type
!= OFPT_ECHO_REPLY
) {
1131 printf("Reply does not match request. Request:\n");
1132 ofp_print(stdout
, request
, request
->size
, 2);
1134 ofp_print(stdout
, reply
, reply
->size
, 2);
1136 printf("%d bytes from %s: xid=%08"PRIx32
" time=%.1f ms\n",
1137 reply
->size
- sizeof *rpy_hdr
, argv
[1], rpy_hdr
->xid
,
1138 (1000*(double)(end
.tv_sec
- start
.tv_sec
))
1139 + (.001*(end
.tv_usec
- start
.tv_usec
)));
1140 ofpbuf_delete(request
);
1141 ofpbuf_delete(reply
);
1147 do_benchmark(const struct settings
*s UNUSED
, int argc UNUSED
, char *argv
[])
1149 size_t max_payload
= 65535 - sizeof(struct ofp_header
);
1150 struct timeval start
, end
;
1151 unsigned int payload_size
, message_size
;
1152 struct vconn
*vconn
;
1157 payload_size
= atoi(argv
[2]);
1158 if (payload_size
> max_payload
) {
1159 ovs_fatal(0, "payload must be between 0 and %zu bytes", max_payload
);
1161 message_size
= sizeof(struct ofp_header
) + payload_size
;
1163 count
= atoi(argv
[3]);
1165 printf("Sending %d packets * %u bytes (with header) = %u bytes total\n",
1166 count
, message_size
, count
* message_size
);
1168 open_vconn(argv
[1], &vconn
);
1169 gettimeofday(&start
, NULL
);
1170 for (i
= 0; i
< count
; i
++) {
1171 struct ofpbuf
*request
, *reply
;
1172 struct ofp_header
*rq_hdr
;
1174 rq_hdr
= make_openflow(message_size
, OFPT_ECHO_REQUEST
, &request
);
1175 memset(rq_hdr
+ 1, 0, payload_size
);
1176 run(vconn_transact(vconn
, request
, &reply
), "transact");
1177 ofpbuf_delete(reply
);
1179 gettimeofday(&end
, NULL
);
1182 duration
= ((1000*(double)(end
.tv_sec
- start
.tv_sec
))
1183 + (.001*(end
.tv_usec
- start
.tv_usec
)));
1184 printf("Finished in %.1f ms (%.0f packets/s) (%.0f bytes/s)\n",
1185 duration
, count
/ (duration
/ 1000.0),
1186 count
* message_size
/ (duration
/ 1000.0));
1190 do_execute(const struct settings
*s UNUSED
, int argc
, char *argv
[])
1192 struct vconn
*vconn
;
1193 struct ofpbuf
*request
;
1194 struct nicira_header
*nicira
;
1195 struct nx_command_reply
*ncr
;
1199 nicira
= make_openflow(sizeof *nicira
, OFPT_VENDOR
, &request
);
1200 xid
= nicira
->header
.xid
;
1201 nicira
->vendor
= htonl(NX_VENDOR_ID
);
1202 nicira
->subtype
= htonl(NXT_COMMAND_REQUEST
);
1203 ofpbuf_put(request
, argv
[2], strlen(argv
[2]));
1204 for (i
= 3; i
< argc
; i
++) {
1205 ofpbuf_put_zeros(request
, 1);
1206 ofpbuf_put(request
, argv
[i
], strlen(argv
[i
]));
1208 update_openflow_length(request
);
1210 open_vconn(argv
[1], &vconn
);
1211 run(vconn_send_block(vconn
, request
), "send");
1214 struct ofpbuf
*reply
;
1217 run(vconn_recv_xid(vconn
, xid
, &reply
), "recv_xid");
1218 if (reply
->size
< sizeof *ncr
) {
1219 ovs_fatal(0, "reply is too short (%zu bytes < %zu bytes)",
1220 reply
->size
, sizeof *ncr
);
1223 if (ncr
->nxh
.header
.type
!= OFPT_VENDOR
1224 || ncr
->nxh
.vendor
!= htonl(NX_VENDOR_ID
)
1225 || ncr
->nxh
.subtype
!= htonl(NXT_COMMAND_REPLY
)) {
1226 ovs_fatal(0, "reply is invalid");
1229 status
= ntohl(ncr
->status
);
1230 if (status
& NXT_STATUS_STARTED
) {
1231 /* Wait for a second reply. */
1233 } else if (status
& NXT_STATUS_EXITED
) {
1234 fprintf(stderr
, "process terminated normally with exit code %d",
1235 status
& NXT_STATUS_EXITSTATUS
);
1236 } else if (status
& NXT_STATUS_SIGNALED
) {
1237 fprintf(stderr
, "process terminated by signal %d",
1238 status
& NXT_STATUS_TERMSIG
);
1239 } else if (status
& NXT_STATUS_ERROR
) {
1240 fprintf(stderr
, "error executing command");
1242 fprintf(stderr
, "process terminated for unknown reason");
1244 if (status
& NXT_STATUS_COREDUMP
) {
1245 fprintf(stderr
, " (core dumped)");
1249 fwrite(ncr
+ 1, reply
->size
- sizeof *ncr
, 1, stdout
);
1255 do_help(const struct settings
*s UNUSED
, int argc UNUSED
, char *argv
[] UNUSED
)
1260 static struct command all_commands
[] = {
1261 { "show", 1, 1, do_show
},
1262 { "status", 1, 2, do_status
},
1263 { "monitor", 1, 3, do_monitor
},
1264 { "dump-desc", 1, 1, do_dump_desc
},
1265 { "dump-tables", 1, 1, do_dump_tables
},
1266 { "dump-flows", 1, 2, do_dump_flows
},
1267 { "dump-aggregate", 1, 2, do_dump_aggregate
},
1268 { "add-flow", 2, 2, do_add_flow
},
1269 { "add-flows", 2, 2, do_add_flows
},
1270 { "mod-flows", 2, 2, do_mod_flows
},
1271 { "del-flows", 1, 2, do_del_flows
},
1272 { "dump-ports", 1, 1, do_dump_ports
},
1273 { "mod-port", 3, 3, do_mod_port
},
1274 { "probe", 1, 1, do_probe
},
1275 { "ping", 1, 2, do_ping
},
1276 { "benchmark", 3, 3, do_benchmark
},
1277 { "execute", 2, INT_MAX
, do_execute
},
1278 { "help", 0, INT_MAX
, do_help
},
1279 { NULL
, 0, 0, NULL
},