2 * Copyright (c) 2008, 2009, 2010 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"
54 #define THIS_MODULE VLM_ofctl
56 #define DEFAULT_IDLE_TIMEOUT 60
58 #define MOD_PORT_CMD_UP "up"
59 #define MOD_PORT_CMD_DOWN "down"
60 #define MOD_PORT_CMD_FLOOD "flood"
61 #define MOD_PORT_CMD_NOFLOOD "noflood"
63 /* Use strict matching for flow mod commands? */
66 static const struct command all_commands
[];
68 static void usage(void) NO_RETURN
;
69 static void parse_options(int argc
, char *argv
[]);
72 main(int argc
, char *argv
[])
74 set_program_name(argv
[0]);
77 parse_options(argc
, argv
);
78 signal(SIGPIPE
, SIG_IGN
);
79 run_command(argc
- optind
, argv
+ optind
, all_commands
);
84 parse_options(int argc
, char *argv
[])
87 OPT_STRICT
= UCHAR_MAX
+ 1,
90 static struct option long_options
[] = {
91 {"timeout", required_argument
, 0, 't'},
92 {"strict", no_argument
, 0, OPT_STRICT
},
93 {"help", no_argument
, 0, 'h'},
94 {"version", no_argument
, 0, 'V'},
96 STREAM_SSL_LONG_OPTIONS
99 char *short_options
= long_options_to_short_options(long_options
);
102 unsigned long int timeout
;
105 c
= getopt_long(argc
, argv
, short_options
, long_options
, NULL
);
112 timeout
= strtoul(optarg
, NULL
, 10);
114 ovs_fatal(0, "value %s on -t or --timeout is not at least 1",
125 OVS_PRINT_VERSION(OFP_VERSION
, OFP_VERSION
);
133 STREAM_SSL_OPTION_HANDLERS
148 printf("%s: OpenFlow switch management utility\n"
149 "usage: %s [OPTIONS] COMMAND [ARG...]\n"
150 "\nFor OpenFlow switches:\n"
151 " show SWITCH show OpenFlow information\n"
152 " status SWITCH [KEY] report statistics (about KEY)\n"
153 " dump-desc SWITCH print switch description\n"
154 " dump-tables SWITCH print table stats\n"
155 " mod-port SWITCH IFACE ACT modify port behavior\n"
156 " dump-ports SWITCH [PORT] print port statistics\n"
157 " dump-flows SWITCH print all flow entries\n"
158 " dump-flows SWITCH FLOW print matching FLOWs\n"
159 " dump-aggregate SWITCH print aggregate flow statistics\n"
160 " dump-aggregate SWITCH FLOW print aggregate stats for FLOWs\n"
161 " add-flow SWITCH FLOW add flow described by FLOW\n"
162 " add-flows SWITCH FILE add flows from FILE\n"
163 " mod-flows SWITCH FLOW modify actions of matching FLOWs\n"
164 " del-flows SWITCH [FLOW] delete matching FLOWs\n"
165 " monitor SWITCH [MISSLEN] print packets received from SWITCH\n"
166 "\nFor OpenFlow switches and controllers:\n"
167 " probe VCONN probe whether VCONN is up\n"
168 " ping VCONN [N] latency of N-byte echos\n"
169 " benchmark VCONN N COUNT bandwidth of COUNT N-byte echos\n"
170 "where each SWITCH is an active OpenFlow connection method.\n",
171 program_name
, program_name
);
172 vconn_usage(true, false, false);
174 printf("\nOther options:\n"
175 " --strict use strict match for flow commands\n"
176 " -t, --timeout=SECS give up after SECS seconds\n"
177 " -h, --help display this help message\n"
178 " -V, --version display version information\n");
182 static void run(int retval
, const char *message
, ...)
185 static void run(int retval
, const char *message
, ...)
190 fprintf(stderr
, "%s: ", program_name
);
191 va_start(args
, message
);
192 vfprintf(stderr
, message
, args
);
195 fputs(": unexpected end of file\n", stderr
);
197 fprintf(stderr
, ": %s\n", strerror(retval
));
204 /* Generic commands. */
207 open_vconn_socket(const char *name
, struct vconn
**vconnp
)
209 char *vconn_name
= xasprintf("unix:%s", name
);
210 VLOG_INFO("connecting to %s", vconn_name
);
211 run(vconn_open_block(vconn_name
, OFP_VERSION
, vconnp
),
212 "connecting to %s", vconn_name
);
217 open_vconn(const char *name
, struct vconn
**vconnp
)
221 char *bridge_path
, *datapath_name
, *datapath_type
;
223 bridge_path
= xasprintf("%s/%s.mgmt", ovs_rundir
, name
);
224 dp_parse_name(name
, &datapath_name
, &datapath_type
);
226 if (strstr(name
, ":")) {
227 run(vconn_open_block(name
, OFP_VERSION
, vconnp
),
228 "connecting to %s", name
);
229 } else if (!stat(name
, &s
) && S_ISSOCK(s
.st_mode
)) {
230 open_vconn_socket(name
, vconnp
);
231 } else if (!stat(bridge_path
, &s
) && S_ISSOCK(s
.st_mode
)) {
232 open_vconn_socket(bridge_path
, vconnp
);
233 } else if (!dpif_open(datapath_name
, datapath_type
, &dpif
)) {
234 char dpif_name
[IF_NAMESIZE
+ 1];
237 run(dpif_port_get_name(dpif
, ODPP_LOCAL
, dpif_name
, sizeof dpif_name
),
238 "obtaining name of %s", dpif_name
);
240 if (strcmp(dpif_name
, name
)) {
241 VLOG_INFO("datapath %s is named %s", name
, dpif_name
);
244 socket_name
= xasprintf("%s/%s.mgmt", ovs_rundir
, dpif_name
);
245 if (stat(socket_name
, &s
)) {
246 ovs_fatal(errno
, "cannot connect to %s: stat failed on %s",
248 } else if (!S_ISSOCK(s
.st_mode
)) {
249 ovs_fatal(0, "cannot connect to %s: %s is not a socket",
253 open_vconn_socket(socket_name
, vconnp
);
256 ovs_fatal(0, "%s is not a valid connection method", name
);
265 alloc_stats_request(size_t body_len
, uint16_t type
, struct ofpbuf
**bufferp
)
267 struct ofp_stats_request
*rq
;
268 rq
= make_openflow((offsetof(struct ofp_stats_request
, body
)
269 + body_len
), OFPT_STATS_REQUEST
, bufferp
);
270 rq
->type
= htons(type
);
271 rq
->flags
= htons(0);
276 send_openflow_buffer(struct vconn
*vconn
, struct ofpbuf
*buffer
)
278 update_openflow_length(buffer
);
279 run(vconn_send_block(vconn
, buffer
), "failed to send packet to switch");
283 dump_transaction(const char *vconn_name
, struct ofpbuf
*request
)
286 struct ofpbuf
*reply
;
288 update_openflow_length(request
);
289 open_vconn(vconn_name
, &vconn
);
290 run(vconn_transact(vconn
, request
, &reply
), "talking to %s", vconn_name
);
291 ofp_print(stdout
, reply
->data
, reply
->size
, 1);
296 dump_trivial_transaction(const char *vconn_name
, uint8_t request_type
)
298 struct ofpbuf
*request
;
299 make_openflow(sizeof(struct ofp_header
), request_type
, &request
);
300 dump_transaction(vconn_name
, request
);
304 dump_stats_transaction(const char *vconn_name
, struct ofpbuf
*request
)
306 uint32_t send_xid
= ((struct ofp_header
*) request
->data
)->xid
;
310 open_vconn(vconn_name
, &vconn
);
311 send_openflow_buffer(vconn
, request
);
314 struct ofpbuf
*reply
;
316 run(vconn_recv_block(vconn
, &reply
), "OpenFlow packet receive failed");
317 recv_xid
= ((struct ofp_header
*) reply
->data
)->xid
;
318 if (send_xid
== recv_xid
) {
319 struct ofp_stats_reply
*osr
;
321 ofp_print(stdout
, reply
->data
, reply
->size
, 1);
323 osr
= ofpbuf_at(reply
, 0, sizeof *osr
);
324 done
= !osr
|| !(ntohs(osr
->flags
) & OFPSF_REPLY_MORE
);
326 VLOG_DBG("received reply with xid %08"PRIx32
" "
327 "!= expected %08"PRIx32
, recv_xid
, send_xid
);
329 ofpbuf_delete(reply
);
335 dump_trivial_stats_transaction(const char *vconn_name
, uint8_t stats_type
)
337 struct ofpbuf
*request
;
338 alloc_stats_request(0, stats_type
, &request
);
339 dump_stats_transaction(vconn_name
, request
);
343 do_show(int argc OVS_UNUSED
, char *argv
[])
345 dump_trivial_transaction(argv
[1], OFPT_FEATURES_REQUEST
);
346 dump_trivial_transaction(argv
[1], OFPT_GET_CONFIG_REQUEST
);
350 do_status(int argc
, char *argv
[])
352 struct nicira_header
*request
, *reply
;
356 request
= make_openflow(sizeof *request
, OFPT_VENDOR
, &b
);
357 request
->vendor
= htonl(NX_VENDOR_ID
);
358 request
->subtype
= htonl(NXT_STATUS_REQUEST
);
360 ofpbuf_put(b
, argv
[2], strlen(argv
[2]));
361 update_openflow_length(b
);
363 open_vconn(argv
[1], &vconn
);
364 run(vconn_transact(vconn
, b
, &b
), "talking to %s", argv
[1]);
367 if (b
->size
< sizeof *reply
) {
368 ovs_fatal(0, "short reply (%zu bytes)", b
->size
);
371 if (reply
->header
.type
!= OFPT_VENDOR
372 || reply
->vendor
!= ntohl(NX_VENDOR_ID
)
373 || reply
->subtype
!= ntohl(NXT_STATUS_REPLY
)) {
374 ofp_print(stderr
, b
->data
, b
->size
, 2);
375 ovs_fatal(0, "bad reply");
378 fwrite(reply
+ 1, b
->size
- sizeof *reply
, 1, stdout
);
382 do_dump_desc(int argc OVS_UNUSED
, char *argv
[])
384 dump_trivial_stats_transaction(argv
[1], OFPST_DESC
);
388 do_dump_tables(int argc OVS_UNUSED
, char *argv
[])
390 dump_trivial_stats_transaction(argv
[1], OFPST_TABLE
);
395 str_to_u32(const char *str
)
401 value
= strtoul(str
, &tail
, 0);
402 if (errno
== EINVAL
|| errno
== ERANGE
|| *tail
) {
403 ovs_fatal(0, "invalid numeric format %s", str
);
409 str_to_u64(const char *str
)
415 value
= strtoull(str
, &tail
, 0);
416 if (errno
== EINVAL
|| errno
== ERANGE
|| *tail
) {
417 ovs_fatal(0, "invalid numeric format %s", str
);
423 str_to_mac(const char *str
, uint8_t mac
[6])
425 if (sscanf(str
, ETH_ADDR_SCAN_FMT
, ETH_ADDR_SCAN_ARGS(mac
))
426 != ETH_ADDR_SCAN_COUNT
) {
427 ovs_fatal(0, "invalid mac address %s", str
);
432 str_to_ip(const char *str_
, uint32_t *ip
)
434 char *str
= xstrdup(str_
);
435 char *save_ptr
= NULL
;
436 const char *name
, *netmask
;
437 struct in_addr in_addr
;
440 name
= strtok_r(str
, "/", &save_ptr
);
441 retval
= name
? lookup_ip(name
, &in_addr
) : EINVAL
;
443 ovs_fatal(0, "%s: could not convert to IP address", str
);
445 *ip
= in_addr
.s_addr
;
447 netmask
= strtok_r(NULL
, "/", &save_ptr
);
450 if (sscanf(netmask
, "%"SCNu8
".%"SCNu8
".%"SCNu8
".%"SCNu8
,
451 &o
[0], &o
[1], &o
[2], &o
[3]) == 4) {
452 uint32_t nm
= (o
[0] << 24) | (o
[1] << 16) | (o
[2] << 8) | o
[3];
455 /* Find first 1-bit. */
456 for (i
= 0; i
< 32; i
++) {
457 if (nm
& (1u << i
)) {
463 /* Verify that the rest of the bits are 1-bits. */
464 for (; i
< 32; i
++) {
465 if (!(nm
& (1u << i
))) {
466 ovs_fatal(0, "%s: %s is not a valid netmask",
471 int prefix
= atoi(netmask
);
472 if (prefix
<= 0 || prefix
> 32) {
473 ovs_fatal(0, "%s: network prefix bits not between 1 and 32",
476 n_wild
= 32 - prefix
;
487 str_to_port_no(const char *vconn_name
, const char *str
)
489 struct ofpbuf
*request
, *reply
;
490 struct ofp_switch_features
*osf
;
494 unsigned int port_no
;
497 /* Check if the argument is a port index. Otherwise, treat it as
499 if (str_to_uint(str
, 10, &port_no
)) {
503 /* Send a "Features Request" to resolve the name into a number. */
504 make_openflow(sizeof(struct ofp_header
), OFPT_FEATURES_REQUEST
, &request
);
505 open_vconn(vconn_name
, &vconn
);
506 run(vconn_transact(vconn
, request
, &reply
), "talking to %s", vconn_name
);
509 n_ports
= (reply
->size
- sizeof *osf
) / sizeof *osf
->ports
;
511 for (port_idx
= 0; port_idx
< n_ports
; port_idx
++) {
512 /* Check argument as an interface name */
513 if (!strncmp((char *)osf
->ports
[port_idx
].name
, str
,
514 sizeof osf
->ports
[0].name
)) {
518 if (port_idx
== n_ports
) {
519 ovs_fatal(0, "couldn't find monitored port: %s", str
);
522 ofpbuf_delete(reply
);
529 put_action(struct ofpbuf
*b
, size_t size
, uint16_t type
)
531 struct ofp_action_header
*ah
= ofpbuf_put_zeros(b
, size
);
532 ah
->type
= htons(type
);
533 ah
->len
= htons(size
);
537 static struct ofp_action_output
*
538 put_output_action(struct ofpbuf
*b
, uint16_t port
)
540 struct ofp_action_output
*oao
= put_action(b
, sizeof *oao
, OFPAT_OUTPUT
);
541 oao
->port
= htons(port
);
546 put_dl_addr_action(struct ofpbuf
*b
, uint16_t type
, const char *addr
)
548 struct ofp_action_dl_addr
*oada
= put_action(b
, sizeof *oada
, type
);
549 str_to_mac(addr
, oada
->dl_addr
);
554 parse_port_name(const char *name
, uint16_t *port
)
560 static const struct pair pairs
[] = {
561 #define DEF_PAIR(NAME) {#NAME, OFPP_##NAME}
567 DEF_PAIR(CONTROLLER
),
572 static const int n_pairs
= ARRAY_SIZE(pairs
);
575 for (i
= 0; i
< n_pairs
; i
++) {
576 if (!strcasecmp(name
, pairs
[i
].name
)) {
577 *port
= pairs
[i
].value
;
585 str_to_action(char *str
, struct ofpbuf
*b
)
588 char *saveptr
= NULL
;
592 for (act
= strtok_r(str
, ", \t\r\n", &saveptr
), n_actions
= 0; act
;
593 act
= strtok_r(NULL
, ", \t\r\n", &saveptr
), n_actions
++)
598 ovs_fatal(0, "Drop actions must not be followed by other actions");
601 /* Arguments are separated by colons */
602 arg
= strchr(act
, ':');
608 if (!strcasecmp(act
, "mod_vlan_vid")) {
609 struct ofp_action_vlan_vid
*va
;
610 va
= put_action(b
, sizeof *va
, OFPAT_SET_VLAN_VID
);
611 va
->vlan_vid
= htons(str_to_u32(arg
));
612 } else if (!strcasecmp(act
, "mod_vlan_pcp")) {
613 struct ofp_action_vlan_pcp
*va
;
614 va
= put_action(b
, sizeof *va
, OFPAT_SET_VLAN_PCP
);
615 va
->vlan_pcp
= str_to_u32(arg
);
616 } else if (!strcasecmp(act
, "strip_vlan")) {
617 struct ofp_action_header
*ah
;
618 ah
= put_action(b
, sizeof *ah
, OFPAT_STRIP_VLAN
);
619 ah
->type
= htons(OFPAT_STRIP_VLAN
);
620 } else if (!strcasecmp(act
, "mod_dl_src")) {
621 put_dl_addr_action(b
, OFPAT_SET_DL_SRC
, arg
);
622 } else if (!strcasecmp(act
, "mod_dl_dst")) {
623 put_dl_addr_action(b
, OFPAT_SET_DL_DST
, arg
);
624 } else if (!strcasecmp(act
, "mod_nw_src")) {
625 struct ofp_action_nw_addr
*na
;
626 na
= put_action(b
, sizeof *na
, OFPAT_SET_NW_SRC
);
627 str_to_ip(arg
, &na
->nw_addr
);
628 } else if (!strcasecmp(act
, "mod_nw_dst")) {
629 struct ofp_action_nw_addr
*na
;
630 na
= put_action(b
, sizeof *na
, OFPAT_SET_NW_DST
);
631 str_to_ip(arg
, &na
->nw_addr
);
632 } else if (!strcasecmp(act
, "mod_tp_src")) {
633 struct ofp_action_tp_port
*ta
;
634 ta
= put_action(b
, sizeof *ta
, OFPAT_SET_TP_SRC
);
635 ta
->tp_port
= htons(str_to_u32(arg
));
636 } else if (!strcasecmp(act
, "mod_tp_dst")) {
637 struct ofp_action_tp_port
*ta
;
638 ta
= put_action(b
, sizeof *ta
, OFPAT_SET_TP_DST
);
639 ta
->tp_port
= htons(str_to_u32(arg
));
640 } else if (!strcasecmp(act
, "mod_nw_tos")) {
641 struct ofp_action_nw_tos
*nt
;
642 nt
= put_action(b
, sizeof *nt
, OFPAT_SET_NW_TOS
);
643 nt
->nw_tos
= str_to_u32(arg
);
644 } else if (!strcasecmp(act
, "resubmit")) {
645 struct nx_action_resubmit
*nar
;
646 nar
= put_action(b
, sizeof *nar
, OFPAT_VENDOR
);
647 nar
->vendor
= htonl(NX_VENDOR_ID
);
648 nar
->subtype
= htons(NXAST_RESUBMIT
);
649 nar
->in_port
= htons(str_to_u32(arg
));
650 } else if (!strcasecmp(act
, "set_tunnel")) {
651 struct nx_action_set_tunnel
*nast
;
652 nast
= put_action(b
, sizeof *nast
, OFPAT_VENDOR
);
653 nast
->vendor
= htonl(NX_VENDOR_ID
);
654 nast
->subtype
= htons(NXAST_SET_TUNNEL
);
655 nast
->tun_id
= htonl(str_to_u32(arg
));
656 } else if (!strcasecmp(act
, "output")) {
657 put_output_action(b
, str_to_u32(arg
));
658 } else if (!strcasecmp(act
, "drop")) {
659 /* A drop action in OpenFlow occurs by just not setting
663 ovs_fatal(0, "Drop actions must not be preceded by other "
666 } else if (!strcasecmp(act
, "CONTROLLER")) {
667 struct ofp_action_output
*oao
;
668 oao
= put_output_action(b
, OFPP_CONTROLLER
);
670 /* Unless a numeric argument is specified, we send the whole
671 * packet to the controller. */
672 if (arg
&& (strspn(arg
, "0123456789") == strlen(arg
))) {
673 oao
->max_len
= htons(str_to_u32(arg
));
675 oao
->max_len
= htons(UINT16_MAX
);
677 } else if (parse_port_name(act
, &port
)) {
678 put_output_action(b
, port
);
679 } else if (strspn(act
, "0123456789") == strlen(act
)) {
680 put_output_action(b
, str_to_u32(act
));
682 ovs_fatal(0, "Unknown action: %s", act
);
694 parse_protocol(const char *name
, const struct protocol
**p_out
)
696 static const struct protocol protocols
[] = {
697 { "ip", ETH_TYPE_IP
, 0 },
698 { "arp", ETH_TYPE_ARP
, 0 },
699 { "icmp", ETH_TYPE_IP
, IP_TYPE_ICMP
},
700 { "tcp", ETH_TYPE_IP
, IP_TYPE_TCP
},
701 { "udp", ETH_TYPE_IP
, IP_TYPE_UDP
},
703 const struct protocol
*p
;
705 for (p
= protocols
; p
< &protocols
[ARRAY_SIZE(protocols
)]; p
++) {
706 if (!strcmp(p
->name
, name
)) {
718 enum { F_U8
, F_U16
, F_MAC
, F_IP
} type
;
719 size_t offset
, shift
;
723 parse_field(const char *name
, const struct field
**f_out
)
725 #define F_OFS(MEMBER) offsetof(struct ofp_match, MEMBER)
726 static const struct field fields
[] = {
727 { "in_port", OFPFW_IN_PORT
, F_U16
, F_OFS(in_port
), 0 },
728 { "dl_vlan", OFPFW_DL_VLAN
, F_U16
, F_OFS(dl_vlan
), 0 },
729 { "dl_vlan_pcp", OFPFW_DL_VLAN_PCP
, F_U8
, F_OFS(dl_vlan_pcp
), 0 },
730 { "dl_src", OFPFW_DL_SRC
, F_MAC
, F_OFS(dl_src
), 0 },
731 { "dl_dst", OFPFW_DL_DST
, F_MAC
, F_OFS(dl_dst
), 0 },
732 { "dl_type", OFPFW_DL_TYPE
, F_U16
, F_OFS(dl_type
), 0 },
733 { "nw_src", OFPFW_NW_SRC_MASK
, F_IP
,
734 F_OFS(nw_src
), OFPFW_NW_SRC_SHIFT
},
735 { "nw_dst", OFPFW_NW_DST_MASK
, F_IP
,
736 F_OFS(nw_dst
), OFPFW_NW_DST_SHIFT
},
737 { "nw_proto", OFPFW_NW_PROTO
, F_U8
, F_OFS(nw_proto
), 0 },
738 { "nw_tos", OFPFW_NW_TOS
, F_U8
, F_OFS(nw_tos
), 0 },
739 { "tp_src", OFPFW_TP_SRC
, F_U16
, F_OFS(tp_src
), 0 },
740 { "tp_dst", OFPFW_TP_DST
, F_U16
, F_OFS(tp_dst
), 0 },
741 { "icmp_type", OFPFW_ICMP_TYPE
, F_U16
, F_OFS(icmp_type
), 0 },
742 { "icmp_code", OFPFW_ICMP_CODE
, F_U16
, F_OFS(icmp_code
), 0 }
744 const struct field
*f
;
746 for (f
= fields
; f
< &fields
[ARRAY_SIZE(fields
)]; f
++) {
747 if (!strcmp(f
->name
, name
)) {
757 str_to_flow(char *string
, struct ofp_match
*match
, struct ofpbuf
*actions
,
758 uint8_t *table_idx
, uint16_t *out_port
, uint16_t *priority
,
759 uint16_t *idle_timeout
, uint16_t *hard_timeout
,
762 char *save_ptr
= NULL
;
770 *out_port
= OFPP_NONE
;
773 *priority
= OFP_DEFAULT_PRIORITY
;
776 *idle_timeout
= DEFAULT_IDLE_TIMEOUT
;
779 *hard_timeout
= OFP_FLOW_PERMANENT
;
785 char *act_str
= strstr(string
, "action");
787 ovs_fatal(0, "must specify an action");
791 act_str
= strchr(act_str
+ 1, '=');
793 ovs_fatal(0, "must specify an action");
798 str_to_action(act_str
, actions
);
800 memset(match
, 0, sizeof *match
);
801 wildcards
= OFPFW_ALL
;
802 for (name
= strtok_r(string
, "=, \t\r\n", &save_ptr
); name
;
803 name
= strtok_r(NULL
, "=, \t\r\n", &save_ptr
)) {
804 const struct protocol
*p
;
806 if (parse_protocol(name
, &p
)) {
807 wildcards
&= ~OFPFW_DL_TYPE
;
808 match
->dl_type
= htons(p
->dl_type
);
810 wildcards
&= ~OFPFW_NW_PROTO
;
811 match
->nw_proto
= p
->nw_proto
;
814 const struct field
*f
;
817 value
= strtok_r(NULL
, ", \t\r\n", &save_ptr
);
819 ovs_fatal(0, "field %s missing value", name
);
822 if (table_idx
&& !strcmp(name
, "table")) {
823 *table_idx
= atoi(value
);
824 } else if (out_port
&& !strcmp(name
, "out_port")) {
825 *out_port
= atoi(value
);
826 } else if (priority
&& !strcmp(name
, "priority")) {
827 *priority
= atoi(value
);
828 } else if (idle_timeout
&& !strcmp(name
, "idle_timeout")) {
829 *idle_timeout
= atoi(value
);
830 } else if (hard_timeout
&& !strcmp(name
, "hard_timeout")) {
831 *hard_timeout
= atoi(value
);
832 } else if (cookie
&& !strcmp(name
, "cookie")) {
833 *cookie
= str_to_u64(value
);
834 } else if (!strcmp(name
, "tun_id_wild")) {
835 wildcards
|= NXFW_TUN_ID
;
836 } else if (parse_field(name
, &f
)) {
837 void *data
= (char *) match
+ f
->offset
;
838 if (!strcmp(value
, "*") || !strcmp(value
, "ANY")) {
839 wildcards
|= f
->wildcard
;
841 wildcards
&= ~f
->wildcard
;
842 if (f
->wildcard
== OFPFW_IN_PORT
843 && parse_port_name(value
, (uint16_t *) data
)) {
845 } else if (f
->type
== F_U8
) {
846 *(uint8_t *) data
= str_to_u32(value
);
847 } else if (f
->type
== F_U16
) {
848 *(uint16_t *) data
= htons(str_to_u32(value
));
849 } else if (f
->type
== F_MAC
) {
850 str_to_mac(value
, data
);
851 } else if (f
->type
== F_IP
) {
852 wildcards
|= str_to_ip(value
, data
) << f
->shift
;
858 ovs_fatal(0, "unknown keyword %s", name
);
862 match
->wildcards
= htonl(wildcards
);
866 do_dump_flows(int argc
, char *argv
[])
868 struct ofp_flow_stats_request
*req
;
870 struct ofpbuf
*request
;
872 req
= alloc_stats_request(sizeof *req
, OFPST_FLOW
, &request
);
873 str_to_flow(argc
> 2 ? argv
[2] : "", &req
->match
, NULL
,
874 &req
->table_id
, &out_port
, NULL
, NULL
, NULL
, NULL
);
875 memset(&req
->pad
, 0, sizeof req
->pad
);
876 req
->out_port
= htons(out_port
);
878 dump_stats_transaction(argv
[1], request
);
882 do_dump_aggregate(int argc
, char *argv
[])
884 struct ofp_aggregate_stats_request
*req
;
885 struct ofpbuf
*request
;
888 req
= alloc_stats_request(sizeof *req
, OFPST_AGGREGATE
, &request
);
889 str_to_flow(argc
> 2 ? argv
[2] : "", &req
->match
, NULL
,
890 &req
->table_id
, &out_port
, NULL
, NULL
, NULL
, NULL
);
891 memset(&req
->pad
, 0, sizeof req
->pad
);
892 req
->out_port
= htons(out_port
);
894 dump_stats_transaction(argv
[1], request
);
898 do_add_flow(int argc OVS_UNUSED
, char *argv
[])
901 struct ofpbuf
*buffer
;
902 struct ofp_flow_mod
*ofm
;
903 uint16_t priority
, idle_timeout
, hard_timeout
;
905 struct ofp_match match
;
907 /* Parse and send. str_to_flow() will expand and reallocate the data in
908 * 'buffer', so we can't keep pointers to across the str_to_flow() call. */
909 make_openflow(sizeof *ofm
, OFPT_FLOW_MOD
, &buffer
);
910 str_to_flow(argv
[2], &match
, buffer
,
911 NULL
, NULL
, &priority
, &idle_timeout
, &hard_timeout
,
915 ofm
->command
= htons(OFPFC_ADD
);
916 ofm
->cookie
= htonll(cookie
);
917 ofm
->idle_timeout
= htons(idle_timeout
);
918 ofm
->hard_timeout
= htons(hard_timeout
);
919 ofm
->buffer_id
= htonl(UINT32_MAX
);
920 ofm
->priority
= htons(priority
);
922 open_vconn(argv
[1], &vconn
);
923 send_openflow_buffer(vconn
, buffer
);
928 do_add_flows(int argc OVS_UNUSED
, char *argv
[])
934 file
= fopen(argv
[2], "r");
936 ovs_fatal(errno
, "%s: open", argv
[2]);
939 open_vconn(argv
[1], &vconn
);
940 while (fgets(line
, sizeof line
, file
)) {
941 struct ofpbuf
*buffer
;
942 struct ofp_flow_mod
*ofm
;
943 uint16_t priority
, idle_timeout
, hard_timeout
;
945 struct ofp_match match
;
949 /* Delete comments. */
950 comment
= strchr(line
, '#');
955 /* Drop empty lines. */
956 if (line
[strspn(line
, " \t\n")] == '\0') {
960 /* Parse and send. str_to_flow() will expand and reallocate the data
961 * in 'buffer', so we can't keep pointers to across the str_to_flow()
963 make_openflow(sizeof *ofm
, OFPT_FLOW_MOD
, &buffer
);
964 str_to_flow(line
, &match
, buffer
,
965 NULL
, NULL
, &priority
, &idle_timeout
, &hard_timeout
,
969 ofm
->command
= htons(OFPFC_ADD
);
970 ofm
->cookie
= htonll(cookie
);
971 ofm
->idle_timeout
= htons(idle_timeout
);
972 ofm
->hard_timeout
= htons(hard_timeout
);
973 ofm
->buffer_id
= htonl(UINT32_MAX
);
974 ofm
->priority
= htons(priority
);
976 send_openflow_buffer(vconn
, buffer
);
983 do_mod_flows(int argc OVS_UNUSED
, char *argv
[])
985 uint16_t priority
, idle_timeout
, hard_timeout
;
988 struct ofpbuf
*buffer
;
989 struct ofp_flow_mod
*ofm
;
990 struct ofp_match match
;
992 /* Parse and send. str_to_flow() will expand and reallocate the data in
993 * 'buffer', so we can't keep pointers to across the str_to_flow() call. */
994 make_openflow(sizeof *ofm
, OFPT_FLOW_MOD
, &buffer
);
995 str_to_flow(argv
[2], &match
, buffer
,
996 NULL
, NULL
, &priority
, &idle_timeout
, &hard_timeout
,
1001 ofm
->command
= htons(OFPFC_MODIFY_STRICT
);
1003 ofm
->command
= htons(OFPFC_MODIFY
);
1005 ofm
->idle_timeout
= htons(idle_timeout
);
1006 ofm
->hard_timeout
= htons(hard_timeout
);
1007 ofm
->cookie
= htonll(cookie
);
1008 ofm
->buffer_id
= htonl(UINT32_MAX
);
1009 ofm
->priority
= htons(priority
);
1011 open_vconn(argv
[1], &vconn
);
1012 send_openflow_buffer(vconn
, buffer
);
1016 static void do_del_flows(int argc
, char *argv
[])
1018 struct vconn
*vconn
;
1021 struct ofpbuf
*buffer
;
1022 struct ofp_flow_mod
*ofm
;
1024 /* Parse and send. */
1025 ofm
= make_openflow(sizeof *ofm
, OFPT_FLOW_MOD
, &buffer
);
1026 str_to_flow(argc
> 2 ? argv
[2] : "", &ofm
->match
, NULL
, NULL
,
1027 &out_port
, &priority
, NULL
, NULL
, NULL
);
1029 ofm
->command
= htons(OFPFC_DELETE_STRICT
);
1031 ofm
->command
= htons(OFPFC_DELETE
);
1033 ofm
->idle_timeout
= htons(0);
1034 ofm
->hard_timeout
= htons(0);
1035 ofm
->buffer_id
= htonl(UINT32_MAX
);
1036 ofm
->out_port
= htons(out_port
);
1037 ofm
->priority
= htons(priority
);
1039 open_vconn(argv
[1], &vconn
);
1040 send_openflow_buffer(vconn
, buffer
);
1045 do_tun_cookie(int argc OVS_UNUSED
, char *argv
[])
1047 struct nxt_tun_id_cookie
*tun_id_cookie
;
1048 struct ofpbuf
*buffer
;
1049 struct vconn
*vconn
;
1051 tun_id_cookie
= make_openflow(sizeof *tun_id_cookie
, OFPT_VENDOR
, &buffer
);
1053 tun_id_cookie
->vendor
= htonl(NX_VENDOR_ID
);
1054 tun_id_cookie
->subtype
= htonl(NXT_TUN_ID_FROM_COOKIE
);
1055 tun_id_cookie
->set
= !strcmp(argv
[2], "true");
1057 open_vconn(argv
[1], &vconn
);
1058 send_openflow_buffer(vconn
, buffer
);
1063 do_monitor(int argc OVS_UNUSED
, char *argv
[])
1065 struct vconn
*vconn
;
1067 open_vconn(argv
[1], &vconn
);
1069 int miss_send_len
= atoi(argv
[2]);
1070 struct ofp_switch_config
*osc
;
1073 osc
= make_openflow(sizeof *osc
, OFPT_SET_CONFIG
, &buf
);
1074 osc
->miss_send_len
= htons(miss_send_len
);
1075 send_openflow_buffer(vconn
, buf
);
1079 run(vconn_recv_block(vconn
, &b
), "vconn_recv");
1080 ofp_print(stderr
, b
->data
, b
->size
, 2);
1086 do_dump_ports(int argc
, char *argv
[])
1088 struct ofp_port_stats_request
*req
;
1089 struct ofpbuf
*request
;
1092 req
= alloc_stats_request(sizeof *req
, OFPST_PORT
, &request
);
1093 port
= argc
> 2 ? str_to_port_no(argv
[1], argv
[2]) : OFPP_NONE
;
1094 req
->port_no
= htons(port
);
1095 dump_stats_transaction(argv
[1], request
);
1099 do_probe(int argc OVS_UNUSED
, char *argv
[])
1101 struct ofpbuf
*request
;
1102 struct vconn
*vconn
;
1103 struct ofpbuf
*reply
;
1105 make_openflow(sizeof(struct ofp_header
), OFPT_ECHO_REQUEST
, &request
);
1106 open_vconn(argv
[1], &vconn
);
1107 run(vconn_transact(vconn
, request
, &reply
), "talking to %s", argv
[1]);
1108 if (reply
->size
!= sizeof(struct ofp_header
)) {
1109 ovs_fatal(0, "reply does not match request");
1111 ofpbuf_delete(reply
);
1116 do_mod_port(int argc OVS_UNUSED
, char *argv
[])
1118 struct ofpbuf
*request
, *reply
;
1119 struct ofp_switch_features
*osf
;
1120 struct ofp_port_mod
*opm
;
1121 struct vconn
*vconn
;
1128 /* Check if the argument is a port index. Otherwise, treat it as
1130 port_no
= strtol(argv
[2], &endptr
, 10);
1131 if (port_no
== 0 && endptr
== argv
[2]) {
1135 /* Send a "Features Request" to get the information we need in order
1136 * to modify the port. */
1137 make_openflow(sizeof(struct ofp_header
), OFPT_FEATURES_REQUEST
, &request
);
1138 open_vconn(argv
[1], &vconn
);
1139 run(vconn_transact(vconn
, request
, &reply
), "talking to %s", argv
[1]);
1142 n_ports
= (reply
->size
- sizeof *osf
) / sizeof *osf
->ports
;
1144 for (port_idx
= 0; port_idx
< n_ports
; port_idx
++) {
1145 if (port_no
!= -1) {
1146 /* Check argument as a port index */
1147 if (osf
->ports
[port_idx
].port_no
== htons(port_no
)) {
1151 /* Check argument as an interface name */
1152 if (!strncmp((char *)osf
->ports
[port_idx
].name
, argv
[2],
1153 sizeof osf
->ports
[0].name
)) {
1159 if (port_idx
== n_ports
) {
1160 ovs_fatal(0, "couldn't find monitored port: %s", argv
[2]);
1163 opm
= make_openflow(sizeof(struct ofp_port_mod
), OFPT_PORT_MOD
, &request
);
1164 opm
->port_no
= osf
->ports
[port_idx
].port_no
;
1165 memcpy(opm
->hw_addr
, osf
->ports
[port_idx
].hw_addr
, sizeof opm
->hw_addr
);
1166 opm
->config
= htonl(0);
1167 opm
->mask
= htonl(0);
1168 opm
->advertise
= htonl(0);
1170 printf("modifying port: %s\n", osf
->ports
[port_idx
].name
);
1172 if (!strncasecmp(argv
[3], MOD_PORT_CMD_UP
, sizeof MOD_PORT_CMD_UP
)) {
1173 opm
->mask
|= htonl(OFPPC_PORT_DOWN
);
1174 } else if (!strncasecmp(argv
[3], MOD_PORT_CMD_DOWN
,
1175 sizeof MOD_PORT_CMD_DOWN
)) {
1176 opm
->mask
|= htonl(OFPPC_PORT_DOWN
);
1177 opm
->config
|= htonl(OFPPC_PORT_DOWN
);
1178 } else if (!strncasecmp(argv
[3], MOD_PORT_CMD_FLOOD
,
1179 sizeof MOD_PORT_CMD_FLOOD
)) {
1180 opm
->mask
|= htonl(OFPPC_NO_FLOOD
);
1181 } else if (!strncasecmp(argv
[3], MOD_PORT_CMD_NOFLOOD
,
1182 sizeof MOD_PORT_CMD_NOFLOOD
)) {
1183 opm
->mask
|= htonl(OFPPC_NO_FLOOD
);
1184 opm
->config
|= htonl(OFPPC_NO_FLOOD
);
1186 ovs_fatal(0, "unknown mod-port command '%s'", argv
[3]);
1189 send_openflow_buffer(vconn
, request
);
1191 ofpbuf_delete(reply
);
1196 do_ping(int argc
, char *argv
[])
1198 size_t max_payload
= 65535 - sizeof(struct ofp_header
);
1199 unsigned int payload
;
1200 struct vconn
*vconn
;
1203 payload
= argc
> 2 ? atoi(argv
[2]) : 64;
1204 if (payload
> max_payload
) {
1205 ovs_fatal(0, "payload must be between 0 and %zu bytes", max_payload
);
1208 open_vconn(argv
[1], &vconn
);
1209 for (i
= 0; i
< 10; i
++) {
1210 struct timeval start
, end
;
1211 struct ofpbuf
*request
, *reply
;
1212 struct ofp_header
*rq_hdr
, *rpy_hdr
;
1214 rq_hdr
= make_openflow(sizeof(struct ofp_header
) + payload
,
1215 OFPT_ECHO_REQUEST
, &request
);
1216 random_bytes(rq_hdr
+ 1, payload
);
1218 gettimeofday(&start
, NULL
);
1219 run(vconn_transact(vconn
, ofpbuf_clone(request
), &reply
), "transact");
1220 gettimeofday(&end
, NULL
);
1222 rpy_hdr
= reply
->data
;
1223 if (reply
->size
!= request
->size
1224 || memcmp(rpy_hdr
+ 1, rq_hdr
+ 1, payload
)
1225 || rpy_hdr
->xid
!= rq_hdr
->xid
1226 || rpy_hdr
->type
!= OFPT_ECHO_REPLY
) {
1227 printf("Reply does not match request. Request:\n");
1228 ofp_print(stdout
, request
, request
->size
, 2);
1230 ofp_print(stdout
, reply
, reply
->size
, 2);
1232 printf("%zu bytes from %s: xid=%08"PRIx32
" time=%.1f ms\n",
1233 reply
->size
- sizeof *rpy_hdr
, argv
[1], rpy_hdr
->xid
,
1234 (1000*(double)(end
.tv_sec
- start
.tv_sec
))
1235 + (.001*(end
.tv_usec
- start
.tv_usec
)));
1236 ofpbuf_delete(request
);
1237 ofpbuf_delete(reply
);
1243 do_benchmark(int argc OVS_UNUSED
, char *argv
[])
1245 size_t max_payload
= 65535 - sizeof(struct ofp_header
);
1246 struct timeval start
, end
;
1247 unsigned int payload_size
, message_size
;
1248 struct vconn
*vconn
;
1253 payload_size
= atoi(argv
[2]);
1254 if (payload_size
> max_payload
) {
1255 ovs_fatal(0, "payload must be between 0 and %zu bytes", max_payload
);
1257 message_size
= sizeof(struct ofp_header
) + payload_size
;
1259 count
= atoi(argv
[3]);
1261 printf("Sending %d packets * %u bytes (with header) = %u bytes total\n",
1262 count
, message_size
, count
* message_size
);
1264 open_vconn(argv
[1], &vconn
);
1265 gettimeofday(&start
, NULL
);
1266 for (i
= 0; i
< count
; i
++) {
1267 struct ofpbuf
*request
, *reply
;
1268 struct ofp_header
*rq_hdr
;
1270 rq_hdr
= make_openflow(message_size
, OFPT_ECHO_REQUEST
, &request
);
1271 memset(rq_hdr
+ 1, 0, payload_size
);
1272 run(vconn_transact(vconn
, request
, &reply
), "transact");
1273 ofpbuf_delete(reply
);
1275 gettimeofday(&end
, NULL
);
1278 duration
= ((1000*(double)(end
.tv_sec
- start
.tv_sec
))
1279 + (.001*(end
.tv_usec
- start
.tv_usec
)));
1280 printf("Finished in %.1f ms (%.0f packets/s) (%.0f bytes/s)\n",
1281 duration
, count
/ (duration
/ 1000.0),
1282 count
* message_size
/ (duration
/ 1000.0));
1286 do_help(int argc OVS_UNUSED
, char *argv
[] OVS_UNUSED
)
1291 static const struct command all_commands
[] = {
1292 { "show", 1, 1, do_show
},
1293 { "status", 1, 2, do_status
},
1294 { "monitor", 1, 2, do_monitor
},
1295 { "dump-desc", 1, 1, do_dump_desc
},
1296 { "dump-tables", 1, 1, do_dump_tables
},
1297 { "dump-flows", 1, 2, do_dump_flows
},
1298 { "dump-aggregate", 1, 2, do_dump_aggregate
},
1299 { "add-flow", 2, 2, do_add_flow
},
1300 { "add-flows", 2, 2, do_add_flows
},
1301 { "mod-flows", 2, 2, do_mod_flows
},
1302 { "del-flows", 1, 2, do_del_flows
},
1303 { "tun-cookie", 2, 2, do_tun_cookie
},
1304 { "dump-ports", 1, 2, do_dump_ports
},
1305 { "mod-port", 3, 3, do_mod_port
},
1306 { "probe", 1, 1, do_probe
},
1307 { "ping", 1, 2, do_ping
},
1308 { "benchmark", 3, 3, do_benchmark
},
1309 { "help", 0, INT_MAX
, do_help
},
1310 { NULL
, 0, 0, NULL
},