diff options
author | Ben Pfaff <blp@ovn.org> | 2017-06-13 17:09:05 -0700 |
---|---|---|
committer | Ben Pfaff <blp@ovn.org> | 2017-06-14 12:50:23 -0700 |
commit | 1b3758c36e88fd261377726f9ab958a0be53f2ca (patch) | |
tree | 12b68e5006754b9a43edc337e537cf25b6181377 | |
parent | 89cf41eca75e28b85423c04f0ed7665a0f160a26 (diff) | |
download | openvswitch-1b3758c36e88fd261377726f9ab958a0be53f2ca.tar.gz |
ovs-ofctl: New option "--no-stats" for "ovs-ofctl dump-flows".
It's pretty common to want to omit statistics from output, to make it
easier to read. This commit adds an ovs-ofctl option to make that easy.
A lot of the OVS internal tests could use this, too, in place of
ofctl_strip. This commit adopts it for a subset.
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Aaron Conole <aconole@redhat.com>
-rw-r--r-- | NEWS | 8 | ||||
-rw-r--r-- | include/openvswitch/ofp-print.h | 2 | ||||
-rw-r--r-- | lib/ofp-print.c | 50 | ||||
-rw-r--r-- | ovn/utilities/ovn-sbctl.c | 6 | ||||
-rw-r--r-- | ovn/utilities/ovn-trace.c | 10 | ||||
-rw-r--r-- | tests/bundle.at | 3 | ||||
-rw-r--r-- | tests/learn.at | 59 | ||||
-rw-r--r-- | utilities/ovs-ofctl.8.in | 14 | ||||
-rw-r--r-- | utilities/ovs-ofctl.c | 12 |
9 files changed, 87 insertions, 77 deletions
@@ -1,8 +1,10 @@ Post-v2.7.0 --------------------- - - ovs-ofctl can now accept and display port names in place of numbers. By - default it always accepts names and in interactive use it displays them; - use --names or --no-names to override. See ovs-ofctl(8) for details. + - ovs-ofctl: + * ovs-ofctl can now accept and display port names in place of numbers. By + default it always accepts names and in interactive use it displays them; + use --names or --no-names to override. See ovs-ofctl(8) for details. + * "ovs-ofctl dump-flows" now accepts --no-stats to omit flow statistics. - Tunnels: * Added support to set packet mark for tunnel endpoint using `egress_pkt_mark` OVSDB option. diff --git a/include/openvswitch/ofp-print.h b/include/openvswitch/ofp-print.h index 4893d44b4..20f049a37 100644 --- a/include/openvswitch/ofp-print.h +++ b/include/openvswitch/ofp-print.h @@ -61,7 +61,7 @@ void ofp_print_table_features( const struct ofputil_table_stats *prev_stats); void ofp_print_flow_stats(struct ds *, const struct ofputil_flow_stats *, - const struct ofputil_port_map *); + const struct ofputil_port_map *, bool show_stats); #ifdef __cplusplus } diff --git a/lib/ofp-print.c b/lib/ofp-print.c index 423df3102..b1c412ea4 100644 --- a/lib/ofp-print.c +++ b/lib/ofp-print.c @@ -1682,21 +1682,34 @@ ofp_print_flow_stats_request(struct ds *string, const struct ofp_header *oh, match_format(&fsr.match, port_map, string, OFP_DEFAULT_PRIORITY); } +/* Appends a textual form of 'fs' to 'string', translating port numbers to + * names using 'port_map' (if provided). If 'show_stats' is true, the output + * includes the flow duration, packet and byte counts, and its idle and hard + * ages, otherwise they are omitted. */ void ofp_print_flow_stats(struct ds *string, const struct ofputil_flow_stats *fs, - const struct ofputil_port_map *port_map) + const struct ofputil_port_map *port_map, bool show_stats) { - ds_put_format(string, " %scookie=%s0x%"PRIx64", %sduration=%s", - colors.param, colors.end, ntohll(fs->cookie), - colors.param, colors.end); - - ofp_print_duration(string, fs->duration_sec, fs->duration_nsec); - ds_put_format(string, ", %stable=%s%"PRIu8", ", - colors.special, colors.end, fs->table_id); - ds_put_format(string, "%sn_packets=%s%"PRIu64", ", - colors.param, colors.end, fs->packet_count); - ds_put_format(string, "%sn_bytes=%s%"PRIu64", ", - colors.param, colors.end, fs->byte_count); + if (show_stats || fs->cookie) { + ds_put_format(string, "%scookie=%s0x%"PRIx64", ", + colors.param, colors.end, ntohll(fs->cookie)); + } + if (show_stats) { + ds_put_format(string, "%sduration=%s", colors.param, colors.end); + ofp_print_duration(string, fs->duration_sec, fs->duration_nsec); + ds_put_cstr(string, ", "); + } + + if (show_stats || fs->table_id) { + ds_put_format(string, "%stable=%s%"PRIu8", ", + colors.special, colors.end, fs->table_id); + } + if (show_stats) { + ds_put_format(string, "%sn_packets=%s%"PRIu64", ", + colors.param, colors.end, fs->packet_count); + ds_put_format(string, "%sn_bytes=%s%"PRIu64", ", + colors.param, colors.end, fs->byte_count); + } if (fs->idle_timeout != OFP_FLOW_PERMANENT) { ds_put_format(string, "%sidle_timeout=%s%"PRIu16", ", colors.param, colors.end, fs->idle_timeout); @@ -1712,17 +1725,20 @@ ofp_print_flow_stats(struct ds *string, const struct ofputil_flow_stats *fs, ds_put_format(string, "%simportance=%s%"PRIu16", ", colors.param, colors.end, fs->importance); } - if (fs->idle_age >= 0) { + if (show_stats && fs->idle_age >= 0) { ds_put_format(string, "%sidle_age=%s%d, ", colors.param, colors.end, fs->idle_age); } - if (fs->hard_age >= 0 && fs->hard_age != fs->duration_sec) { + if (show_stats && fs->hard_age >= 0 && fs->hard_age != fs->duration_sec) { ds_put_format(string, "%shard_age=%s%d, ", colors.param, colors.end, fs->hard_age); } + /* Print the match, followed by a space (but omit the space if the match + * was an empty string). */ + size_t length = string->length; match_format(&fs->match, port_map, string, fs->priority); - if (string->string[string->length - 1] != ' ') { + if (string->length != length) { ds_put_char(string, ' '); } @@ -1749,8 +1765,8 @@ ofp_print_flow_stats_reply(struct ds *string, const struct ofp_header *oh, } break; } - ds_put_char(string, '\n'); - ofp_print_flow_stats(string, &fs, port_map); + ds_put_cstr(string, "\n "); + ofp_print_flow_stats(string, &fs, port_map, true); } ofpbuf_uninit(&ofpacts); } diff --git a/ovn/utilities/ovn-sbctl.c b/ovn/utilities/ovn-sbctl.c index e28a966e6..fc9f8e5fd 100644 --- a/ovn/utilities/ovn-sbctl.c +++ b/ovn/utilities/ovn-sbctl.c @@ -793,9 +793,9 @@ sbctl_dump_openflow(struct vconn *vconn, const struct uuid *uuid, bool stats) ds_clear(&s); if (stats) { - ofp_print_flow_stats(&s, fs, NULL); + ofp_print_flow_stats(&s, fs, NULL, true); } else { - ds_put_format(&s, " %stable=%s%"PRIu8" ", + ds_put_format(&s, "%stable=%s%"PRIu8" ", colors.special, colors.end, fs->table_id); match_format(&fs->match, NULL, &s, OFP_DEFAULT_PRIORITY); if (ds_last(&s) != ' ') { @@ -805,7 +805,7 @@ sbctl_dump_openflow(struct vconn *vconn, const struct uuid *uuid, bool stats) ds_put_format(&s, "%sactions=%s", colors.actions, colors.end); ofpacts_format(fs->ofpacts, fs->ofpacts_len, NULL, &s); } - printf(" %s\n", ds_cstr(&s)); + printf(" %s\n", ds_cstr(&s)); } ds_destroy(&s); } diff --git a/ovn/utilities/ovn-trace.c b/ovn/utilities/ovn-trace.c index ae42814de..8bdb7d8a3 100644 --- a/ovn/utilities/ovn-trace.c +++ b/ovn/utilities/ovn-trace.c @@ -1878,13 +1878,9 @@ trace_openflow(const struct ovntrace_flow *f, struct ovs_list *super) struct ds s = DS_EMPTY_INITIALIZER; for (size_t i = 0; i < n_fses; i++) { ds_clear(&s); - ofp_print_flow_stats(&s, &fses[i], NULL); - - /* ofp_print_flow_stats() indents its output with a space. - * Omit it. */ - const char *p = ds_cstr(&s); - p += strspn(p, " "); - ovntrace_node_append(super, OVNTRACE_NODE_ACTION, "%s", p); + ofp_print_flow_stats(&s, &fses[i], NULL, true); + ovntrace_node_append(super, OVNTRACE_NODE_ACTION, + "%s", ds_cstr(&s)); } ds_destroy(&s); } else { diff --git a/tests/bundle.at b/tests/bundle.at index 0b6a19222..40dfbea37 100644 --- a/tests/bundle.at +++ b/tests/bundle.at @@ -212,9 +212,8 @@ AT_SETUP([bundle action with many ports]) AT_KEYWORDS([bundle_action]) OVS_VSWITCHD_START AT_CHECK([ovs-ofctl add-flow br0 'actions=set_field:0x1->metadata,set_field:0x2->metadata,set_field:0x3->metadata,set_field:0x4->metadata,bundle(symmetric_l4,0,hrw,ofport,slaves:[[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40]])']) -AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl +AT_CHECK([ovs-ofctl dump-flows br0 --no-stats], [0], [dnl actions=load:0x1->OXM_OF_METADATA[[]],load:0x2->OXM_OF_METADATA[[]],load:0x3->OXM_OF_METADATA[[]],load:0x4->OXM_OF_METADATA[[]],bundle(symmetric_l4,0,hrw,ofport,slaves:1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40) -NXST_FLOW reply: ]) OVS_VSWITCHD_STOP AT_CLEANUP diff --git a/tests/learn.at b/tests/learn.at index 7dd4ca0e0..72e22c4bf 100644 --- a/tests/learn.at +++ b/tests/learn.at @@ -132,10 +132,9 @@ mv stdout expout AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual"], [0], [expout]) # Check for the MAC learning entry. -AT_CHECK([ovs-ofctl dump-flows br0 table=1 | ofctl_strip | sort], [0], [dnl - table=1, hard_timeout=60, vlan_tci=0x0000/0x0fff,dl_dst=50:54:00:00:00:05 actions=output:3 +AT_CHECK([ovs-ofctl dump-flows br0 table=1 --no-stats --sort], [0], [dnl table=1, priority=0 actions=FLOOD -NXST_FLOW reply: + table=1, hard_timeout=60, vlan_tci=0x0000/0x0fff,dl_dst=50:54:00:00:00:05 actions=output:3 ]) # Trace a packet arrival destined for the learned MAC. @@ -145,11 +144,10 @@ AT_CHECK([tail -1 stdout], [0], [Datapath actions: 3 ]) # Check for both MAC learning entries. -AT_CHECK([ovs-ofctl dump-flows br0 table=1 | ofctl_strip |sort], [0], [dnl +AT_CHECK([ovs-ofctl dump-flows br0 table=1 --no-stats | sort], [0], [dnl table=1, hard_timeout=60, vlan_tci=0x0000/0x0fff,dl_dst=50:54:00:00:00:05 actions=output:3 table=1, hard_timeout=60, vlan_tci=0x0000/0x0fff,dl_dst=50:54:00:00:00:06 actions=output:1 table=1, priority=0 actions=FLOOD -NXST_FLOW reply: ]) # Trace a packet arrival that updates the first learned MAC entry. @@ -163,11 +161,10 @@ mv stdout expout AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual"], [0], [expout]) # Check that the MAC learning entry was updated. -AT_CHECK([ovs-ofctl dump-flows br0 table=1 | ofctl_strip | sort], [0], [dnl +AT_CHECK([ovs-ofctl dump-flows br0 table=1 --no-stats | sort], [0], [dnl table=1, hard_timeout=60, vlan_tci=0x0000/0x0fff,dl_dst=50:54:00:00:00:05 actions=output:2 table=1, hard_timeout=60, vlan_tci=0x0000/0x0fff,dl_dst=50:54:00:00:00:06 actions=output:1 table=1, priority=0 actions=FLOOD -NXST_FLOW reply: ]) OVS_VSWITCHD_STOP AT_CLEANUP @@ -204,10 +201,9 @@ mv stdout expout AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual"], [0], [expout]) # Check that the MAC learning entry appeared. -AT_CHECK([ovs-ofctl dump-flows br0 table=1 | ofctl_strip | sort], [0], [dnl +AT_CHECK([ovs-ofctl dump-flows br0 table=1 --no-stats | sort], [0], [dnl table=1, hard_timeout=10, dl_dst=50:54:00:00:00:07 actions=output:3 table=1, priority=0 actions=FLOOD -NXST_FLOW reply: ]) # For 25 seconds, make sure that the MAC learning entry doesn't @@ -239,9 +235,8 @@ done # Make sure that 15 seconds without refreshing makes the flow time out. ovs-appctl time/warp 15000 5000 sleep 1 -AT_CHECK([ovs-ofctl dump-flows br0 table=1 | ofctl_strip | sort], [0], [dnl +AT_CHECK([ovs-ofctl dump-flows br0 table=1 --no-stats | sort], [0], [dnl table=1, priority=0 actions=FLOOD -NXST_FLOW reply: ]) OVS_VSWITCHD_STOP AT_CLEANUP @@ -265,9 +260,8 @@ mv stdout expout AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual"], [0], [expout]) # Check for the learning entry. -AT_CHECK([ovs-ofctl dump-flows br0 table=1 | ofctl_strip | sort], [0], [dnl +AT_CHECK([ovs-ofctl dump-flows br0 table=1 --no-stats | sort], [0], [dnl table=1, hard_timeout=60, tcp,nw_src=192.168.0.1,nw_dst=192.168.0.2,tp_src=80,tp_dst=40000 actions=drop -NXST_FLOW reply: ]) OVS_VSWITCHD_STOP AT_CLEANUP @@ -293,10 +287,9 @@ mv stdout expout AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual"], [0], [expout]) # Check for the learning entry. -AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl +AT_CHECK([ovs-ofctl dump-flows br0 --no-stats | sort], [0], [dnl table=1, hard_timeout=60, tcp6,ipv6_src=fec0::1,ipv6_dst=2001:db8:85a3::8a2e:370:7334,tp_src=80,tp_dst=40000 actions=load:0x13198a2e03707348->NXM_NX_IPV6_DST[[0..63]],load:0x20010db885a308d3->NXM_NX_IPV6_DST[[64..127]] tcp6 actions=learn(table=1,hard_timeout=60,eth_type=0x86dd,nw_proto=6,NXM_NX_IPV6_SRC[[]]=NXM_NX_IPV6_DST[[]],ipv6_dst=2001:db8:85a3::8a2e:370:7334,NXM_OF_TCP_SRC[[]]=NXM_OF_TCP_DST[[]],NXM_OF_TCP_DST[[]]=NXM_OF_TCP_SRC[[]],load:0x20010db885a308d313198a2e03707348->NXM_NX_IPV6_DST[[]]),FLOOD -NXST_FLOW reply: ]) OVS_VSWITCHD_STOP AT_CLEANUP @@ -508,9 +501,8 @@ OVS_VSWITCHD_START( [add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1]) AT_CHECK([[ovs-ofctl add-flow br0 'actions=learn(fin_hard_timeout=10, fin_idle_timeout=5, NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[], output:NXM_OF_IN_PORT[])']]) AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:05,dst=ff:ff:ff:ff:ff:ff),eth_type(0x0806),arp(sip=192.168.0.1,tip=192.168.0.2,op=1,sha=50:54:00:00:00:05,tha=00:00:00:00:00:00)' -generate], [0], [ignore]) -AT_CHECK([ovs-ofctl dump-flows br0 table=1 | ofctl_strip], [0], -[NXST_FLOW reply: - table=1, dl_dst=50:54:00:00:00:05 actions=fin_timeout(idle_timeout=5,hard_timeout=10),output:1 +AT_CHECK([ovs-ofctl dump-flows br0 table=1 --no-stats], [0], +[ table=1, dl_dst=50:54:00:00:00:05 actions=fin_timeout(idle_timeout=5,hard_timeout=10),output:1 ]) OVS_VSWITCHD_STOP AT_CLEANUP @@ -528,65 +520,59 @@ cookie=0x123, table=2, reg0=0x5 actions=drop cookie=0x234, table=1, reg0=0x6 actions=drop ]) AT_CHECK([ovs-ofctl add-flows br0 flows.txt]) -AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl +AT_CHECK([ovs-ofctl dump-flows br0 --no-stats | sort], [0], [dnl cookie=0x123, table=1, reg0=0x3 actions=drop cookie=0x123, table=1, reg0=0x4 actions=drop cookie=0x123, table=2, reg0=0x5 actions=drop cookie=0x234, table=1, reg0=0x6 actions=drop reg0=0x1 actions=learn(table=1,delete_learned,cookie=0x123) reg0=0x2 actions=learn(table=1,delete_learned,cookie=0x123) -NXST_FLOW reply: ]) # Delete one of the learn actions. The learned flows should stay, since there # is another learn action with the identical target. AT_CHECK([ovs-ofctl del-flows br0 'table=0 reg0=1']) -AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl +AT_CHECK([ovs-ofctl dump-flows br0 --no-stats | sort], [0], [dnl cookie=0x123, table=1, reg0=0x3 actions=drop cookie=0x123, table=1, reg0=0x4 actions=drop cookie=0x123, table=2, reg0=0x5 actions=drop cookie=0x234, table=1, reg0=0x6 actions=drop reg0=0x2 actions=learn(table=1,delete_learned,cookie=0x123) -NXST_FLOW reply: ]) # Change the flow with the learn action by adding a second action. The learned # flows should stay because the learn action is still there. AT_CHECK([ovs-ofctl mod-flows br0 'table=0 reg0=2 actions=output:1,learn(delete_learned,cookie=0x123)']) -AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl +AT_CHECK([ovs-ofctl dump-flows br0 --no-stats | sort], [0], [dnl cookie=0x123, table=1, reg0=0x3 actions=drop cookie=0x123, table=1, reg0=0x4 actions=drop cookie=0x123, table=2, reg0=0x5 actions=drop cookie=0x234, table=1, reg0=0x6 actions=drop reg0=0x2 actions=output:1,learn(table=1,delete_learned,cookie=0x123) -NXST_FLOW reply: ]) # Change the flow with the learn action by replacing its learn action by one # with a different target. The (previous) learned flows disappear. AT_CHECK([ovs-ofctl mod-flows br0 'table=0 reg0=2 actions=learn(delete_learned,cookie=0x234)']) -AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl +AT_CHECK([ovs-ofctl dump-flows br0 --no-stats | sort], [0], [dnl cookie=0x123, table=2, reg0=0x5 actions=drop cookie=0x234, table=1, reg0=0x6 actions=drop reg0=0x2 actions=learn(table=1,delete_learned,cookie=0x234) -NXST_FLOW reply: ]) # Use add-flow to replace the flow with the learn action by one with the # same learn action and an extra action. The (new) learned flow remains. AT_CHECK([ovs-ofctl add-flow br0 'table=0 reg0=2 actions=learn(delete_learned,cookie=0x234),output:2']) -AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl +AT_CHECK([ovs-ofctl dump-flows br0 --no-stats | sort], [0], [dnl cookie=0x123, table=2, reg0=0x5 actions=drop cookie=0x234, table=1, reg0=0x6 actions=drop reg0=0x2 actions=learn(table=1,delete_learned,cookie=0x234),output:2 -NXST_FLOW reply: ]) # Delete the flow with the learn action. The learned flow disappears too. AT_CHECK([ovs-ofctl del-flows br0 table=0]) -AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl +AT_CHECK([ovs-ofctl dump-flows br0 --no-stats | sort], [0], [dnl cookie=0x123, table=2, reg0=0x5 actions=drop -NXST_FLOW reply: ]) # Add a new set of flows to check on a corner case: the learned flows @@ -608,7 +594,7 @@ cookie=0x567, table=5, reg0=0x8 actions=drop ]) AT_CHECK([ovs-ofctl del-flows br0]) AT_CHECK([ovs-ofctl add-flows br0 flows.txt]) -AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl +AT_CHECK([ovs-ofctl dump-flows br0 --no-stats | sort], [0], [dnl cookie=0x123, table=1, reg0=0x3 actions=learn(table=3,delete_learned,cookie=0x345) cookie=0x234, table=2, reg0=0x3 actions=learn(table=4,delete_learned,cookie=0x456) cookie=0x345, table=3, reg0=0x4 actions=learn(table=5,delete_learned,cookie=0x567) @@ -618,28 +604,24 @@ AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl cookie=0x567, table=5, reg0=0x8 actions=drop reg0=0x1 actions=learn(table=1,delete_learned,cookie=0x123) reg0=0x2 actions=learn(table=2,delete_learned,cookie=0x234) -NXST_FLOW reply: ]) # Deleting the flow with reg0=1 should cascade to delete a few levels # of learned flows, but the ones with cookie=0x567 stick around # because of the flow with cookie=0x456. AT_CHECK([ovs-ofctl del-flows br0 'table=0 reg0=1']) -AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl +AT_CHECK([ovs-ofctl dump-flows br0 --no-stats | sort], [0], [dnl cookie=0x234, table=2, reg0=0x3 actions=learn(table=4,delete_learned,cookie=0x456) cookie=0x456, table=4, reg0=0x5 actions=learn(table=5,delete_learned,cookie=0x567) cookie=0x567, table=5, reg0=0x6 actions=drop cookie=0x567, table=5, reg0=0x7 actions=drop cookie=0x567, table=5, reg0=0x8 actions=drop reg0=0x2 actions=learn(table=2,delete_learned,cookie=0x234) -NXST_FLOW reply: ]) # Deleting the flow with reg0=2 should cascade to delete all the rest: AT_CHECK([ovs-ofctl del-flows br0 'table=0 reg0=2']) -AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl -NXST_FLOW reply: -]) +AT_CHECK([ovs-ofctl dump-flows br0 --no-stats | sort]) OVS_VSWITCHD_STOP AT_CLEANUP @@ -656,9 +638,8 @@ AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00: OVS_WAIT_UNTIL([ovs-ofctl dump-ports br0 2 | grep -o 'tx pkts=2' >/dev/null]) -AT_CHECK([ovs-ofctl dump-flows br0 table=1 | ofctl_strip | sort], [0], [dnl +AT_CHECK([ovs-ofctl dump-flows br0 table=1 --no-stats], [0], [dnl cookie=0x1, table=1, dl_dst=50:54:00:00:00:01 actions=drop -NXST_FLOW reply: ]) dnl Delete the learned flow diff --git a/utilities/ovs-ofctl.8.in b/utilities/ovs-ofctl.8.in index 3b86c0d73..65525908a 100644 --- a/utilities/ovs-ofctl.8.in +++ b/utilities/ovs-ofctl.8.in @@ -222,8 +222,11 @@ syntax of \fIflows\fR. The output format is described in .IP By default, \fBovs\-ofctl\fR prints flow entries in the same order that the switch sends them, which is unlikely to be intuitive or -consistent. See the description of \fB\-\-sort\fR and \fB\-\-rsort\fR, -under \fBOPTIONS\fR below, to influence the display order. +consistent. Use \fB\-\-sort\fR and \fB\-\-rsort\fR to control display +order. The \fB\-\-names\fR/\fB\-\-no\-names\fR and +\fB\-\-stats\fR/\fB\-\-no\-stats\fR options also affect output +formatting. See the descriptions of these options, under +\fBOPTIONS\fR below, for more information . .TP \fBdump\-aggregate \fIswitch \fR[\fIflows\fR] @@ -2222,6 +2225,13 @@ be the same; when a switch has two ports with the same (truncated) name, \fBovs\-ofctl\fR refuses to display or accept the name, using the number instead. . +.IP "\fB\-\-stats\fR" +.IQ "\fB\-\-no\-stats\fR" +The \fBdump\-flows\fR command by default, or with \fB\-\-stats\fR, +includes flow duration, packet and byte counts, and idle and hard age +in its output. With \fB\-\-no\-stats\fR, it omits all of these, as +well as cookie values and table IDs if they are zero. +. .IP "\fB\-\-read-only\fR" Do not execute read/write commands. . diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c index 95989eb11..d7e37e85f 100644 --- a/utilities/ovs-ofctl.c +++ b/utilities/ovs-ofctl.c @@ -135,6 +135,9 @@ static const struct ofputil_port_map *ports_to_show(const char *vconn_name); static bool should_accept_ports(void); static bool should_show_ports(void); +/* --stats, --no-stats: Show statistics in flow dumps? */ +static int show_stats = 1; + static const struct ovs_cmdl_command *get_all_commands(void); OVS_NO_RETURN static void usage(void); @@ -212,6 +215,8 @@ parse_options(int argc, char *argv[]) {"rsort", optional_argument, NULL, OPT_RSORT}, {"names", no_argument, &use_port_names, 1}, {"no-names", no_argument, &use_port_names, 0}, + {"stats", no_argument, &show_stats, 1}, + {"no-stats", no_argument, &show_stats, 0}, {"unixctl", required_argument, NULL, OPT_UNIXCTL}, {"help", no_argument, NULL, 'h'}, {"option", no_argument, NULL, 'o'}, @@ -1357,7 +1362,7 @@ compare_flows(const void *afs_, const void *bfs_) static void ofctl_dump_flows(struct ovs_cmdl_context *ctx) { - if (!n_criteria && !should_show_ports()) { + if (!n_criteria && !should_show_ports() && show_stats) { ofctl_dump_flows__(ctx->argc, ctx->argv, false); return; } else { @@ -1378,8 +1383,9 @@ ofctl_dump_flows(struct ovs_cmdl_context *ctx) struct ds s = DS_EMPTY_INITIALIZER; for (size_t i = 0; i < n_fses; i++) { ds_clear(&s); - ofp_print_flow_stats(&s, &fses[i], ports_to_show(ctx->argv[1])); - puts(ds_cstr(&s)); + ofp_print_flow_stats(&s, &fses[i], ports_to_show(ctx->argv[1]), + show_stats); + printf(" %s\n", ds_cstr(&s)); } ds_destroy(&s); |