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"
47 #include "stream-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"
62 /* Use strict matching for flow mod commands? */
65 static const struct command all_commands
[];
67 static void usage(void) NO_RETURN
;
68 static void parse_options(int argc
, char *argv
[]);
71 main(int argc
, char *argv
[])
73 set_program_name(argv
[0]);
76 parse_options(argc
, argv
);
77 signal(SIGPIPE
, SIG_IGN
);
78 run_command(argc
- optind
, argv
+ optind
, all_commands
);
83 parse_options(int argc
, char *argv
[])
86 OPT_STRICT
= UCHAR_MAX
+ 1
88 static struct option long_options
[] = {
89 {"timeout", required_argument
, 0, 't'},
90 {"verbose", optional_argument
, 0, 'v'},
91 {"strict", no_argument
, 0, OPT_STRICT
},
92 {"help", no_argument
, 0, 'h'},
93 {"version", no_argument
, 0, 'V'},
94 STREAM_SSL_LONG_OPTIONS
97 char *short_options
= long_options_to_short_options(long_options
);
100 unsigned long int timeout
;
103 c
= getopt_long(argc
, argv
, short_options
, long_options
, NULL
);
110 timeout
= strtoul(optarg
, NULL
, 10);
112 ovs_fatal(0, "value %s on -t or --timeout is not at least 1",
123 OVS_PRINT_VERSION(OFP_VERSION
, OFP_VERSION
);
127 vlog_set_verbosity(optarg
);
134 STREAM_SSL_OPTION_HANDLERS
149 printf("%s: OpenFlow switch management utility\n"
150 "usage: %s [OPTIONS] COMMAND [ARG...]\n"
151 "\nFor OpenFlow switches:\n"
152 " show SWITCH show OpenFlow information\n"
153 " status SWITCH [KEY] report statistics (about KEY)\n"
154 " dump-desc SWITCH print switch description\n"
155 " dump-tables SWITCH print table stats\n"
156 " mod-port SWITCH IFACE ACT modify port behavior\n"
157 " dump-ports SWITCH print port statistics\n"
158 " dump-flows SWITCH print all flow entries\n"
159 " dump-flows SWITCH FLOW print matching FLOWs\n"
160 " dump-aggregate SWITCH print aggregate flow statistics\n"
161 " dump-aggregate SWITCH FLOW print aggregate stats for FLOWs\n"
162 " add-flow SWITCH FLOW add flow described by FLOW\n"
163 " add-flows SWITCH FILE add flows from FILE\n"
164 " mod-flows SWITCH FLOW modify actions of matching FLOWs\n"
165 " del-flows SWITCH [FLOW] delete matching FLOWs\n"
166 " monitor SWITCH MISSLEN EXP print packets received from SWITCH\n"
167 "\nFor OpenFlow switches and controllers:\n"
168 " probe VCONN probe whether VCONN is up\n"
169 " ping VCONN [N] latency of N-byte echos\n"
170 " benchmark VCONN N COUNT bandwidth of COUNT N-byte echos\n"
171 "where each SWITCH is an active OpenFlow connection method.\n",
172 program_name
, program_name
);
173 vconn_usage(true, false, false);
175 printf("\nOther options:\n"
176 " --strict use strict match for flow commands\n"
177 " -t, --timeout=SECS give up after SECS seconds\n"
178 " -h, --help display this help message\n"
179 " -V, --version display version information\n");
183 static void run(int retval
, const char *message
, ...)
186 static void run(int retval
, const char *message
, ...)
191 fprintf(stderr
, "%s: ", program_name
);
192 va_start(args
, message
);
193 vfprintf(stderr
, message
, args
);
196 fputs(": unexpected end of file\n", stderr
);
198 fprintf(stderr
, ": %s\n", strerror(retval
));
205 /* Generic commands. */
208 open_vconn_socket(const char *name
, struct vconn
**vconnp
)
210 char *vconn_name
= xasprintf("unix:%s", name
);
211 VLOG_INFO("connecting to %s", vconn_name
);
212 run(vconn_open_block(vconn_name
, OFP_VERSION
, vconnp
),
213 "connecting to %s", vconn_name
);
218 open_vconn(const char *name
, struct vconn
**vconnp
)
222 char *bridge_path
, *datapath_name
, *datapath_type
;
224 bridge_path
= xasprintf("%s/%s.mgmt", ovs_rundir
, name
);
225 dp_parse_name(name
, &datapath_name
, &datapath_type
);
227 if (strstr(name
, ":")) {
228 run(vconn_open_block(name
, OFP_VERSION
, vconnp
),
229 "connecting to %s", name
);
230 } else if (!stat(name
, &s
) && S_ISSOCK(s
.st_mode
)) {
231 open_vconn_socket(name
, vconnp
);
232 } else if (!stat(bridge_path
, &s
) && S_ISSOCK(s
.st_mode
)) {
233 open_vconn_socket(bridge_path
, vconnp
);
234 } else if (!dpif_open(datapath_name
, datapath_type
, &dpif
)) {
235 char dpif_name
[IF_NAMESIZE
+ 1];
238 run(dpif_port_get_name(dpif
, ODPP_LOCAL
, dpif_name
, sizeof dpif_name
),
239 "obtaining name of %s", dpif_name
);
241 if (strcmp(dpif_name
, name
)) {
242 VLOG_INFO("datapath %s is named %s", name
, dpif_name
);
245 socket_name
= xasprintf("%s/%s.mgmt", ovs_rundir
, dpif_name
);
246 if (stat(socket_name
, &s
)) {
247 ovs_fatal(errno
, "cannot connect to %s: stat failed on %s",
249 } else if (!S_ISSOCK(s
.st_mode
)) {
250 ovs_fatal(0, "cannot connect to %s: %s is not a socket",
254 open_vconn_socket(socket_name
, vconnp
);
257 ovs_fatal(0, "%s is not a valid connection method", name
);
266 alloc_stats_request(size_t body_len
, uint16_t type
, struct ofpbuf
**bufferp
)
268 struct ofp_stats_request
*rq
;
269 rq
= make_openflow((offsetof(struct ofp_stats_request
, body
)
270 + body_len
), OFPT_STATS_REQUEST
, bufferp
);
271 rq
->type
= htons(type
);
272 rq
->flags
= htons(0);
277 send_openflow_buffer(struct vconn
*vconn
, struct ofpbuf
*buffer
)
279 update_openflow_length(buffer
);
280 run(vconn_send_block(vconn
, buffer
), "failed to send packet to switch");
284 dump_transaction(const char *vconn_name
, struct ofpbuf
*request
)
287 struct ofpbuf
*reply
;
289 update_openflow_length(request
);
290 open_vconn(vconn_name
, &vconn
);
291 run(vconn_transact(vconn
, request
, &reply
), "talking to %s", vconn_name
);
292 ofp_print(stdout
, reply
->data
, reply
->size
, 1);
297 dump_trivial_transaction(const char *vconn_name
, uint8_t request_type
)
299 struct ofpbuf
*request
;
300 make_openflow(sizeof(struct ofp_header
), request_type
, &request
);
301 dump_transaction(vconn_name
, request
);
305 dump_stats_transaction(const char *vconn_name
, struct ofpbuf
*request
)
307 uint32_t send_xid
= ((struct ofp_header
*) request
->data
)->xid
;
311 open_vconn(vconn_name
, &vconn
);
312 send_openflow_buffer(vconn
, request
);
315 struct ofpbuf
*reply
;
317 run(vconn_recv_block(vconn
, &reply
), "OpenFlow packet receive failed");
318 recv_xid
= ((struct ofp_header
*) reply
->data
)->xid
;
319 if (send_xid
== recv_xid
) {
320 struct ofp_stats_reply
*osr
;
322 ofp_print(stdout
, reply
->data
, reply
->size
, 1);
324 osr
= ofpbuf_at(reply
, 0, sizeof *osr
);
325 done
= !osr
|| !(ntohs(osr
->flags
) & OFPSF_REPLY_MORE
);
327 VLOG_DBG("received reply with xid %08"PRIx32
" "
328 "!= expected %08"PRIx32
, recv_xid
, send_xid
);
330 ofpbuf_delete(reply
);
336 dump_trivial_stats_transaction(const char *vconn_name
, uint8_t stats_type
)
338 struct ofpbuf
*request
;
339 alloc_stats_request(0, stats_type
, &request
);
340 dump_stats_transaction(vconn_name
, request
);
344 do_show(int argc UNUSED
, char *argv
[])
346 dump_trivial_transaction(argv
[1], OFPT_FEATURES_REQUEST
);
347 dump_trivial_transaction(argv
[1], OFPT_GET_CONFIG_REQUEST
);
351 do_status(int argc
, char *argv
[])
353 struct nicira_header
*request
, *reply
;
357 request
= make_openflow(sizeof *request
, OFPT_VENDOR
, &b
);
358 request
->vendor
= htonl(NX_VENDOR_ID
);
359 request
->subtype
= htonl(NXT_STATUS_REQUEST
);
361 ofpbuf_put(b
, argv
[2], strlen(argv
[2]));
362 update_openflow_length(b
);
364 open_vconn(argv
[1], &vconn
);
365 run(vconn_transact(vconn
, b
, &b
), "talking to %s", argv
[1]);
368 if (b
->size
< sizeof *reply
) {
369 ovs_fatal(0, "short reply (%zu bytes)", b
->size
);
372 if (reply
->header
.type
!= OFPT_VENDOR
373 || reply
->vendor
!= ntohl(NX_VENDOR_ID
)
374 || reply
->subtype
!= ntohl(NXT_STATUS_REPLY
)) {
375 ofp_print(stderr
, b
->data
, b
->size
, 2);
376 ovs_fatal(0, "bad reply");
379 fwrite(reply
+ 1, b
->size
- sizeof *reply
, 1, stdout
);
383 do_dump_desc(int argc UNUSED
, char *argv
[])
385 dump_trivial_stats_transaction(argv
[1], OFPST_DESC
);
389 do_dump_tables(int argc UNUSED
, char *argv
[])
391 dump_trivial_stats_transaction(argv
[1], OFPST_TABLE
);
396 str_to_u32(const char *str
)
402 value
= strtoul(str
, &tail
, 0);
403 if (errno
== EINVAL
|| errno
== ERANGE
|| *tail
) {
404 ovs_fatal(0, "invalid numeric format %s", str
);
410 str_to_mac(const char *str
, uint8_t mac
[6])
412 if (sscanf(str
, ETH_ADDR_SCAN_FMT
, ETH_ADDR_SCAN_ARGS(mac
))
413 != ETH_ADDR_SCAN_COUNT
) {
414 ovs_fatal(0, "invalid mac address %s", str
);
419 str_to_ip(const char *str_
, uint32_t *ip
)
421 char *str
= xstrdup(str_
);
422 char *save_ptr
= NULL
;
423 const char *name
, *netmask
;
424 struct in_addr in_addr
;
427 name
= strtok_r(str
, "/", &save_ptr
);
428 retval
= name
? lookup_ip(name
, &in_addr
) : EINVAL
;
430 ovs_fatal(0, "%s: could not convert to IP address", str
);
432 *ip
= in_addr
.s_addr
;
434 netmask
= strtok_r(NULL
, "/", &save_ptr
);
437 if (sscanf(netmask
, "%"SCNu8
".%"SCNu8
".%"SCNu8
".%"SCNu8
,
438 &o
[0], &o
[1], &o
[2], &o
[3]) == 4) {
439 uint32_t nm
= (o
[0] << 24) | (o
[1] << 16) | (o
[2] << 8) | o
[3];
442 /* Find first 1-bit. */
443 for (i
= 0; i
< 32; i
++) {
444 if (nm
& (1u << i
)) {
450 /* Verify that the rest of the bits are 1-bits. */
451 for (; i
< 32; i
++) {
452 if (!(nm
& (1u << i
))) {
453 ovs_fatal(0, "%s: %s is not a valid netmask",
458 int prefix
= atoi(netmask
);
459 if (prefix
<= 0 || prefix
> 32) {
460 ovs_fatal(0, "%s: network prefix bits not between 1 and 32",
463 n_wild
= 32 - prefix
;
474 put_action(struct ofpbuf
*b
, size_t size
, uint16_t type
)
476 struct ofp_action_header
*ah
= ofpbuf_put_zeros(b
, size
);
477 ah
->type
= htons(type
);
478 ah
->len
= htons(size
);
482 static struct ofp_action_output
*
483 put_output_action(struct ofpbuf
*b
, uint16_t port
)
485 struct ofp_action_output
*oao
= put_action(b
, sizeof *oao
, OFPAT_OUTPUT
);
486 oao
->port
= htons(port
);
491 put_dl_addr_action(struct ofpbuf
*b
, uint16_t type
, const char *addr
)
493 struct ofp_action_dl_addr
*oada
= put_action(b
, sizeof *oada
, type
);
494 str_to_mac(addr
, oada
->dl_addr
);
499 parse_port_name(const char *name
, uint16_t *port
)
505 static const struct pair pairs
[] = {
506 #define DEF_PAIR(NAME) {#NAME, OFPP_##NAME}
512 DEF_PAIR(CONTROLLER
),
517 static const int n_pairs
= ARRAY_SIZE(pairs
);
520 for (i
= 0; i
< n_pairs
; i
++) {
521 if (!strcasecmp(name
, pairs
[i
].name
)) {
522 *port
= pairs
[i
].value
;
530 str_to_action(char *str
, struct ofpbuf
*b
)
533 char *saveptr
= NULL
;
537 for (act
= strtok_r(str
, ", \t\r\n", &saveptr
), n_actions
= 0; act
;
538 act
= strtok_r(NULL
, ", \t\r\n", &saveptr
), n_actions
++)
543 ovs_fatal(0, "Drop actions must not be followed by other actions");
546 /* Arguments are separated by colons */
547 arg
= strchr(act
, ':');
553 if (!strcasecmp(act
, "mod_vlan_vid")) {
554 struct ofp_action_vlan_vid
*va
;
555 va
= put_action(b
, sizeof *va
, OFPAT_SET_VLAN_VID
);
556 va
->vlan_vid
= htons(str_to_u32(arg
));
557 } else if (!strcasecmp(act
, "mod_vlan_pcp")) {
558 struct ofp_action_vlan_pcp
*va
;
559 va
= put_action(b
, sizeof *va
, OFPAT_SET_VLAN_PCP
);
560 va
->vlan_pcp
= str_to_u32(arg
);
561 } else if (!strcasecmp(act
, "strip_vlan")) {
562 struct ofp_action_header
*ah
;
563 ah
= put_action(b
, sizeof *ah
, OFPAT_STRIP_VLAN
);
564 ah
->type
= htons(OFPAT_STRIP_VLAN
);
565 } else if (!strcasecmp(act
, "mod_dl_src")) {
566 put_dl_addr_action(b
, OFPAT_SET_DL_SRC
, arg
);
567 } else if (!strcasecmp(act
, "mod_dl_dst")) {
568 put_dl_addr_action(b
, OFPAT_SET_DL_DST
, arg
);
569 } else if (!strcasecmp(act
, "mod_nw_src")) {
570 struct ofp_action_nw_addr
*na
;
571 na
= put_action(b
, sizeof *na
, OFPAT_SET_NW_SRC
);
572 str_to_ip(arg
, &na
->nw_addr
);
573 } else if (!strcasecmp(act
, "mod_nw_dst")) {
574 struct ofp_action_nw_addr
*na
;
575 na
= put_action(b
, sizeof *na
, OFPAT_SET_NW_DST
);
576 str_to_ip(arg
, &na
->nw_addr
);
577 } else if (!strcasecmp(act
, "mod_tp_src")) {
578 struct ofp_action_tp_port
*ta
;
579 ta
= put_action(b
, sizeof *ta
, OFPAT_SET_TP_SRC
);
580 ta
->tp_port
= htons(str_to_u32(arg
));
581 } else if (!strcasecmp(act
, "mod_tp_dst")) {
582 struct ofp_action_tp_port
*ta
;
583 ta
= put_action(b
, sizeof *ta
, OFPAT_SET_TP_DST
);
584 ta
->tp_port
= htons(str_to_u32(arg
));
585 } else if (!strcasecmp(act
, "output")) {
586 put_output_action(b
, str_to_u32(arg
));
587 } else if (!strcasecmp(act
, "drop")) {
588 /* A drop action in OpenFlow occurs by just not setting
592 ovs_fatal(0, "Drop actions must not be preceded by other "
595 } else if (!strcasecmp(act
, "CONTROLLER")) {
596 struct ofp_action_output
*oao
;
597 oao
= put_output_action(b
, OFPP_CONTROLLER
);
599 /* Unless a numeric argument is specified, we send the whole
600 * packet to the controller. */
601 if (arg
&& (strspn(act
, "0123456789") == strlen(act
))) {
602 oao
->max_len
= htons(str_to_u32(arg
));
604 oao
->max_len
= htons(UINT16_MAX
);
606 } else if (parse_port_name(act
, &port
)) {
607 put_output_action(b
, port
);
608 } else if (strspn(act
, "0123456789") == strlen(act
)) {
609 put_output_action(b
, str_to_u32(act
));
611 ovs_fatal(0, "Unknown action: %s", act
);
623 parse_protocol(const char *name
, const struct protocol
**p_out
)
625 static const struct protocol protocols
[] = {
626 { "ip", ETH_TYPE_IP
, 0 },
627 { "arp", ETH_TYPE_ARP
, 0 },
628 { "icmp", ETH_TYPE_IP
, IP_TYPE_ICMP
},
629 { "tcp", ETH_TYPE_IP
, IP_TYPE_TCP
},
630 { "udp", ETH_TYPE_IP
, IP_TYPE_UDP
},
632 const struct protocol
*p
;
634 for (p
= protocols
; p
< &protocols
[ARRAY_SIZE(protocols
)]; p
++) {
635 if (!strcmp(p
->name
, name
)) {
647 enum { F_U8
, F_U16
, F_MAC
, F_IP
} type
;
648 size_t offset
, shift
;
652 parse_field(const char *name
, const struct field
**f_out
)
654 #define F_OFS(MEMBER) offsetof(struct ofp_match, MEMBER)
655 static const struct field fields
[] = {
656 { "in_port", OFPFW_IN_PORT
, F_U16
, F_OFS(in_port
), 0 },
657 { "dl_vlan", OFPFW_DL_VLAN
, F_U16
, F_OFS(dl_vlan
), 0 },
658 { "dl_src", OFPFW_DL_SRC
, F_MAC
, F_OFS(dl_src
), 0 },
659 { "dl_dst", OFPFW_DL_DST
, F_MAC
, F_OFS(dl_dst
), 0 },
660 { "dl_type", OFPFW_DL_TYPE
, F_U16
, F_OFS(dl_type
), 0 },
661 { "nw_src", OFPFW_NW_SRC_MASK
, F_IP
,
662 F_OFS(nw_src
), OFPFW_NW_SRC_SHIFT
},
663 { "nw_dst", OFPFW_NW_DST_MASK
, F_IP
,
664 F_OFS(nw_dst
), OFPFW_NW_DST_SHIFT
},
665 { "nw_proto", OFPFW_NW_PROTO
, F_U8
, F_OFS(nw_proto
), 0 },
666 { "tp_src", OFPFW_TP_SRC
, F_U16
, F_OFS(tp_src
), 0 },
667 { "tp_dst", OFPFW_TP_DST
, F_U16
, F_OFS(tp_dst
), 0 },
668 { "icmp_type", OFPFW_ICMP_TYPE
, F_U16
, F_OFS(icmp_type
), 0 },
669 { "icmp_code", OFPFW_ICMP_CODE
, F_U16
, F_OFS(icmp_code
), 0 }
671 const struct field
*f
;
673 for (f
= fields
; f
< &fields
[ARRAY_SIZE(fields
)]; f
++) {
674 if (!strcmp(f
->name
, name
)) {
684 str_to_flow(char *string
, struct ofp_match
*match
, struct ofpbuf
*actions
,
685 uint8_t *table_idx
, uint16_t *out_port
, uint16_t *priority
,
686 uint16_t *idle_timeout
, uint16_t *hard_timeout
)
688 char *save_ptr
= NULL
;
696 *out_port
= OFPP_NONE
;
699 *priority
= OFP_DEFAULT_PRIORITY
;
702 *idle_timeout
= DEFAULT_IDLE_TIMEOUT
;
705 *hard_timeout
= OFP_FLOW_PERMANENT
;
708 char *act_str
= strstr(string
, "action");
710 ovs_fatal(0, "must specify an action");
714 act_str
= strchr(act_str
, '=');
716 ovs_fatal(0, "must specify an action");
721 str_to_action(act_str
, actions
);
723 memset(match
, 0, sizeof *match
);
724 wildcards
= OFPFW_ALL
;
725 for (name
= strtok_r(string
, "=, \t\r\n", &save_ptr
); name
;
726 name
= strtok_r(NULL
, "=, \t\r\n", &save_ptr
)) {
727 const struct protocol
*p
;
729 if (parse_protocol(name
, &p
)) {
730 wildcards
&= ~OFPFW_DL_TYPE
;
731 match
->dl_type
= htons(p
->dl_type
);
733 wildcards
&= ~OFPFW_NW_PROTO
;
734 match
->nw_proto
= p
->nw_proto
;
737 const struct field
*f
;
740 value
= strtok_r(NULL
, ", \t\r\n", &save_ptr
);
742 ovs_fatal(0, "field %s missing value", name
);
745 if (table_idx
&& !strcmp(name
, "table")) {
746 *table_idx
= atoi(value
);
747 } else if (out_port
&& !strcmp(name
, "out_port")) {
748 *out_port
= atoi(value
);
749 } else if (priority
&& !strcmp(name
, "priority")) {
750 *priority
= atoi(value
);
751 } else if (idle_timeout
&& !strcmp(name
, "idle_timeout")) {
752 *idle_timeout
= atoi(value
);
753 } else if (hard_timeout
&& !strcmp(name
, "hard_timeout")) {
754 *hard_timeout
= atoi(value
);
755 } else if (parse_field(name
, &f
)) {
756 void *data
= (char *) match
+ f
->offset
;
757 if (!strcmp(value
, "*") || !strcmp(value
, "ANY")) {
758 wildcards
|= f
->wildcard
;
760 wildcards
&= ~f
->wildcard
;
761 if (f
->wildcard
== OFPFW_IN_PORT
762 && parse_port_name(value
, (uint16_t *) data
)) {
764 } else if (f
->type
== F_U8
) {
765 *(uint8_t *) data
= str_to_u32(value
);
766 } else if (f
->type
== F_U16
) {
767 *(uint16_t *) data
= htons(str_to_u32(value
));
768 } else if (f
->type
== F_MAC
) {
769 str_to_mac(value
, data
);
770 } else if (f
->type
== F_IP
) {
771 wildcards
|= str_to_ip(value
, data
) << f
->shift
;
777 ovs_fatal(0, "unknown keyword %s", name
);
781 match
->wildcards
= htonl(wildcards
);
785 do_dump_flows(int argc
, char *argv
[])
787 struct ofp_flow_stats_request
*req
;
789 struct ofpbuf
*request
;
791 req
= alloc_stats_request(sizeof *req
, OFPST_FLOW
, &request
);
792 str_to_flow(argc
> 2 ? argv
[2] : "", &req
->match
, NULL
,
793 &req
->table_id
, &out_port
, NULL
, NULL
, NULL
);
794 memset(&req
->pad
, 0, sizeof req
->pad
);
795 req
->out_port
= htons(out_port
);
797 dump_stats_transaction(argv
[1], request
);
801 do_dump_aggregate(int argc
, char *argv
[])
803 struct ofp_aggregate_stats_request
*req
;
804 struct ofpbuf
*request
;
807 req
= alloc_stats_request(sizeof *req
, OFPST_AGGREGATE
, &request
);
808 str_to_flow(argc
> 2 ? argv
[2] : "", &req
->match
, NULL
,
809 &req
->table_id
, &out_port
, NULL
, NULL
, NULL
);
810 memset(&req
->pad
, 0, sizeof req
->pad
);
811 req
->out_port
= htons(out_port
);
813 dump_stats_transaction(argv
[1], request
);
817 do_add_flow(int argc UNUSED
, char *argv
[])
820 struct ofpbuf
*buffer
;
821 struct ofp_flow_mod
*ofm
;
822 uint16_t priority
, idle_timeout
, hard_timeout
;
823 struct ofp_match match
;
825 /* Parse and send. str_to_flow() will expand and reallocate the data in
826 * 'buffer', so we can't keep pointers to across the str_to_flow() call. */
827 make_openflow(sizeof *ofm
, OFPT_FLOW_MOD
, &buffer
);
828 str_to_flow(argv
[2], &match
, buffer
,
829 NULL
, NULL
, &priority
, &idle_timeout
, &hard_timeout
);
832 ofm
->command
= htons(OFPFC_ADD
);
833 ofm
->idle_timeout
= htons(idle_timeout
);
834 ofm
->hard_timeout
= htons(hard_timeout
);
835 ofm
->buffer_id
= htonl(UINT32_MAX
);
836 ofm
->priority
= htons(priority
);
837 ofm
->reserved
= htonl(0);
839 open_vconn(argv
[1], &vconn
);
840 send_openflow_buffer(vconn
, buffer
);
845 do_add_flows(int argc UNUSED
, char *argv
[])
851 file
= fopen(argv
[2], "r");
853 ovs_fatal(errno
, "%s: open", argv
[2]);
856 open_vconn(argv
[1], &vconn
);
857 while (fgets(line
, sizeof line
, file
)) {
858 struct ofpbuf
*buffer
;
859 struct ofp_flow_mod
*ofm
;
860 uint16_t priority
, idle_timeout
, hard_timeout
;
861 struct ofp_match match
;
865 /* Delete comments. */
866 comment
= strchr(line
, '#');
871 /* Drop empty lines. */
872 if (line
[strspn(line
, " \t\n")] == '\0') {
876 /* Parse and send. str_to_flow() will expand and reallocate the data
877 * in 'buffer', so we can't keep pointers to across the str_to_flow()
879 ofm
= make_openflow(sizeof *ofm
, OFPT_FLOW_MOD
, &buffer
);
880 str_to_flow(line
, &match
, buffer
,
881 NULL
, NULL
, &priority
, &idle_timeout
, &hard_timeout
);
884 ofm
->command
= htons(OFPFC_ADD
);
885 ofm
->idle_timeout
= htons(idle_timeout
);
886 ofm
->hard_timeout
= htons(hard_timeout
);
887 ofm
->buffer_id
= htonl(UINT32_MAX
);
888 ofm
->priority
= htons(priority
);
889 ofm
->reserved
= htonl(0);
891 send_openflow_buffer(vconn
, buffer
);
898 do_mod_flows(int argc UNUSED
, char *argv
[])
900 uint16_t priority
, idle_timeout
, hard_timeout
;
902 struct ofpbuf
*buffer
;
903 struct ofp_flow_mod
*ofm
;
904 struct ofp_match match
;
906 /* Parse and send. str_to_flow() will expand and reallocate the data in
907 * 'buffer', so we can't keep pointers to across the str_to_flow() call. */
908 make_openflow(sizeof *ofm
, OFPT_FLOW_MOD
, &buffer
);
909 str_to_flow(argv
[2], &match
, buffer
,
910 NULL
, NULL
, &priority
, &idle_timeout
, &hard_timeout
);
914 ofm
->command
= htons(OFPFC_MODIFY_STRICT
);
916 ofm
->command
= htons(OFPFC_MODIFY
);
918 ofm
->idle_timeout
= htons(idle_timeout
);
919 ofm
->hard_timeout
= htons(hard_timeout
);
920 ofm
->buffer_id
= htonl(UINT32_MAX
);
921 ofm
->priority
= htons(priority
);
922 ofm
->reserved
= htonl(0);
924 open_vconn(argv
[1], &vconn
);
925 send_openflow_buffer(vconn
, buffer
);
929 static void do_del_flows(int argc
, char *argv
[])
934 struct ofpbuf
*buffer
;
935 struct ofp_flow_mod
*ofm
;
937 /* Parse and send. */
938 ofm
= make_openflow(sizeof *ofm
, OFPT_FLOW_MOD
, &buffer
);
939 str_to_flow(argc
> 2 ? argv
[2] : "", &ofm
->match
, NULL
, NULL
,
940 &out_port
, &priority
, NULL
, NULL
);
942 ofm
->command
= htons(OFPFC_DELETE_STRICT
);
944 ofm
->command
= htons(OFPFC_DELETE
);
946 ofm
->idle_timeout
= htons(0);
947 ofm
->hard_timeout
= htons(0);
948 ofm
->buffer_id
= htonl(UINT32_MAX
);
949 ofm
->out_port
= htons(out_port
);
950 ofm
->priority
= htons(priority
);
951 ofm
->reserved
= htonl(0);
953 open_vconn(argv
[1], &vconn
);
954 send_openflow_buffer(vconn
, buffer
);
959 do_monitor(int argc UNUSED
, char *argv
[])
963 open_vconn(argv
[1], &vconn
);
965 int miss_send_len
= atoi(argv
[2]);
966 int send_flow_exp
= argc
> 3 ? atoi(argv
[3]) : 0;
967 struct ofp_switch_config
*osc
;
970 osc
= make_openflow(sizeof *osc
, OFPT_SET_CONFIG
, &buf
);
971 osc
->flags
= htons(send_flow_exp
? OFPC_SEND_FLOW_EXP
: 0);
972 osc
->miss_send_len
= htons(miss_send_len
);
973 send_openflow_buffer(vconn
, buf
);
977 run(vconn_recv_block(vconn
, &b
), "vconn_recv");
978 ofp_print(stderr
, b
->data
, b
->size
, 2);
984 do_dump_ports(int argc UNUSED
, char *argv
[])
986 dump_trivial_stats_transaction(argv
[1], OFPST_PORT
);
990 do_probe(int argc UNUSED
, char *argv
[])
992 struct ofpbuf
*request
;
994 struct ofpbuf
*reply
;
996 make_openflow(sizeof(struct ofp_header
), OFPT_ECHO_REQUEST
, &request
);
997 open_vconn(argv
[1], &vconn
);
998 run(vconn_transact(vconn
, request
, &reply
), "talking to %s", argv
[1]);
999 if (reply
->size
!= sizeof(struct ofp_header
)) {
1000 ovs_fatal(0, "reply does not match request");
1002 ofpbuf_delete(reply
);
1007 do_mod_port(int argc UNUSED
, char *argv
[])
1009 struct ofpbuf
*request
, *reply
;
1010 struct ofp_switch_features
*osf
;
1011 struct ofp_port_mod
*opm
;
1012 struct vconn
*vconn
;
1019 /* Check if the argument is a port index. Otherwise, treat it as
1021 port_no
= strtol(argv
[2], &endptr
, 10);
1022 if (port_no
== 0 && endptr
== argv
[2]) {
1026 /* Send a "Features Request" to get the information we need in order
1027 * to modify the port. */
1028 make_openflow(sizeof(struct ofp_header
), OFPT_FEATURES_REQUEST
, &request
);
1029 open_vconn(argv
[1], &vconn
);
1030 run(vconn_transact(vconn
, request
, &reply
), "talking to %s", argv
[1]);
1033 n_ports
= (reply
->size
- sizeof *osf
) / sizeof *osf
->ports
;
1035 for (port_idx
= 0; port_idx
< n_ports
; port_idx
++) {
1036 if (port_no
!= -1) {
1037 /* Check argument as a port index */
1038 if (osf
->ports
[port_idx
].port_no
== htons(port_no
)) {
1042 /* Check argument as an interface name */
1043 if (!strncmp((char *)osf
->ports
[port_idx
].name
, argv
[2],
1044 sizeof osf
->ports
[0].name
)) {
1050 if (port_idx
== n_ports
) {
1051 ovs_fatal(0, "couldn't find monitored port: %s", argv
[2]);
1054 opm
= make_openflow(sizeof(struct ofp_port_mod
), OFPT_PORT_MOD
, &request
);
1055 opm
->port_no
= osf
->ports
[port_idx
].port_no
;
1056 memcpy(opm
->hw_addr
, osf
->ports
[port_idx
].hw_addr
, sizeof opm
->hw_addr
);
1057 opm
->config
= htonl(0);
1058 opm
->mask
= htonl(0);
1059 opm
->advertise
= htonl(0);
1061 printf("modifying port: %s\n", osf
->ports
[port_idx
].name
);
1063 if (!strncasecmp(argv
[3], MOD_PORT_CMD_UP
, sizeof MOD_PORT_CMD_UP
)) {
1064 opm
->mask
|= htonl(OFPPC_PORT_DOWN
);
1065 } else if (!strncasecmp(argv
[3], MOD_PORT_CMD_DOWN
,
1066 sizeof MOD_PORT_CMD_DOWN
)) {
1067 opm
->mask
|= htonl(OFPPC_PORT_DOWN
);
1068 opm
->config
|= htonl(OFPPC_PORT_DOWN
);
1069 } else if (!strncasecmp(argv
[3], MOD_PORT_CMD_FLOOD
,
1070 sizeof MOD_PORT_CMD_FLOOD
)) {
1071 opm
->mask
|= htonl(OFPPC_NO_FLOOD
);
1072 } else if (!strncasecmp(argv
[3], MOD_PORT_CMD_NOFLOOD
,
1073 sizeof MOD_PORT_CMD_NOFLOOD
)) {
1074 opm
->mask
|= htonl(OFPPC_NO_FLOOD
);
1075 opm
->config
|= htonl(OFPPC_NO_FLOOD
);
1077 ovs_fatal(0, "unknown mod-port command '%s'", argv
[3]);
1080 send_openflow_buffer(vconn
, request
);
1082 ofpbuf_delete(reply
);
1087 do_ping(int argc
, char *argv
[])
1089 size_t max_payload
= 65535 - sizeof(struct ofp_header
);
1090 unsigned int payload
;
1091 struct vconn
*vconn
;
1094 payload
= argc
> 2 ? atoi(argv
[2]) : 64;
1095 if (payload
> max_payload
) {
1096 ovs_fatal(0, "payload must be between 0 and %zu bytes", max_payload
);
1099 open_vconn(argv
[1], &vconn
);
1100 for (i
= 0; i
< 10; i
++) {
1101 struct timeval start
, end
;
1102 struct ofpbuf
*request
, *reply
;
1103 struct ofp_header
*rq_hdr
, *rpy_hdr
;
1105 rq_hdr
= make_openflow(sizeof(struct ofp_header
) + payload
,
1106 OFPT_ECHO_REQUEST
, &request
);
1107 random_bytes(rq_hdr
+ 1, payload
);
1109 gettimeofday(&start
, NULL
);
1110 run(vconn_transact(vconn
, ofpbuf_clone(request
), &reply
), "transact");
1111 gettimeofday(&end
, NULL
);
1113 rpy_hdr
= reply
->data
;
1114 if (reply
->size
!= request
->size
1115 || memcmp(rpy_hdr
+ 1, rq_hdr
+ 1, payload
)
1116 || rpy_hdr
->xid
!= rq_hdr
->xid
1117 || rpy_hdr
->type
!= OFPT_ECHO_REPLY
) {
1118 printf("Reply does not match request. Request:\n");
1119 ofp_print(stdout
, request
, request
->size
, 2);
1121 ofp_print(stdout
, reply
, reply
->size
, 2);
1123 printf("%zu bytes from %s: xid=%08"PRIx32
" time=%.1f ms\n",
1124 reply
->size
- sizeof *rpy_hdr
, argv
[1], rpy_hdr
->xid
,
1125 (1000*(double)(end
.tv_sec
- start
.tv_sec
))
1126 + (.001*(end
.tv_usec
- start
.tv_usec
)));
1127 ofpbuf_delete(request
);
1128 ofpbuf_delete(reply
);
1134 do_benchmark(int argc UNUSED
, char *argv
[])
1136 size_t max_payload
= 65535 - sizeof(struct ofp_header
);
1137 struct timeval start
, end
;
1138 unsigned int payload_size
, message_size
;
1139 struct vconn
*vconn
;
1144 payload_size
= atoi(argv
[2]);
1145 if (payload_size
> max_payload
) {
1146 ovs_fatal(0, "payload must be between 0 and %zu bytes", max_payload
);
1148 message_size
= sizeof(struct ofp_header
) + payload_size
;
1150 count
= atoi(argv
[3]);
1152 printf("Sending %d packets * %u bytes (with header) = %u bytes total\n",
1153 count
, message_size
, count
* message_size
);
1155 open_vconn(argv
[1], &vconn
);
1156 gettimeofday(&start
, NULL
);
1157 for (i
= 0; i
< count
; i
++) {
1158 struct ofpbuf
*request
, *reply
;
1159 struct ofp_header
*rq_hdr
;
1161 rq_hdr
= make_openflow(message_size
, OFPT_ECHO_REQUEST
, &request
);
1162 memset(rq_hdr
+ 1, 0, payload_size
);
1163 run(vconn_transact(vconn
, request
, &reply
), "transact");
1164 ofpbuf_delete(reply
);
1166 gettimeofday(&end
, NULL
);
1169 duration
= ((1000*(double)(end
.tv_sec
- start
.tv_sec
))
1170 + (.001*(end
.tv_usec
- start
.tv_usec
)));
1171 printf("Finished in %.1f ms (%.0f packets/s) (%.0f bytes/s)\n",
1172 duration
, count
/ (duration
/ 1000.0),
1173 count
* message_size
/ (duration
/ 1000.0));
1177 do_help(int argc UNUSED
, char *argv
[] UNUSED
)
1182 static const struct command all_commands
[] = {
1183 { "show", 1, 1, do_show
},
1184 { "status", 1, 2, do_status
},
1185 { "monitor", 1, 3, do_monitor
},
1186 { "dump-desc", 1, 1, do_dump_desc
},
1187 { "dump-tables", 1, 1, do_dump_tables
},
1188 { "dump-flows", 1, 2, do_dump_flows
},
1189 { "dump-aggregate", 1, 2, do_dump_aggregate
},
1190 { "add-flow", 2, 2, do_add_flow
},
1191 { "add-flows", 2, 2, do_add_flows
},
1192 { "mod-flows", 2, 2, do_mod_flows
},
1193 { "del-flows", 1, 2, do_del_flows
},
1194 { "dump-ports", 1, 1, do_dump_ports
},
1195 { "mod-port", 3, 3, do_mod_port
},
1196 { "probe", 1, 1, do_probe
},
1197 { "ping", 1, 2, do_ping
},
1198 { "benchmark", 3, 3, do_benchmark
},
1199 { "help", 0, INT_MAX
, do_help
},
1200 { NULL
, 0, 0, NULL
},