2
0
mirror of https://github.com/openvswitch/ovs synced 2025-08-30 13:58:14 +00:00

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>
This commit is contained in:
Ben Pfaff 2017-06-13 17:09:05 -07:00
parent 89cf41eca7
commit 1b3758c36e
9 changed files with 86 additions and 76 deletions

4
NEWS
View File

@ -1,8 +1,10 @@
Post-v2.7.0 Post-v2.7.0
--------------------- ---------------------
- ovs-ofctl can now accept and display port names in place of numbers. By - 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; 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. 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: - Tunnels:
* Added support to set packet mark for tunnel endpoint using * Added support to set packet mark for tunnel endpoint using
`egress_pkt_mark` OVSDB option. `egress_pkt_mark` OVSDB option.

View File

@ -61,7 +61,7 @@ void ofp_print_table_features(
const struct ofputil_table_stats *prev_stats); const struct ofputil_table_stats *prev_stats);
void ofp_print_flow_stats(struct ds *, const struct ofputil_flow_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 #ifdef __cplusplus
} }

View File

@ -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); 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 void
ofp_print_flow_stats(struct ds *string, const struct ofputil_flow_stats *fs, 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", if (show_stats || fs->cookie) {
colors.param, colors.end, ntohll(fs->cookie), ds_put_format(string, "%scookie=%s0x%"PRIx64", ",
colors.param, colors.end); 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); ofp_print_duration(string, fs->duration_sec, fs->duration_nsec);
ds_put_format(string, ", %stable=%s%"PRIu8", ", ds_put_cstr(string, ", ");
}
if (show_stats || fs->table_id) {
ds_put_format(string, "%stable=%s%"PRIu8", ",
colors.special, colors.end, fs->table_id); colors.special, colors.end, fs->table_id);
}
if (show_stats) {
ds_put_format(string, "%sn_packets=%s%"PRIu64", ", ds_put_format(string, "%sn_packets=%s%"PRIu64", ",
colors.param, colors.end, fs->packet_count); colors.param, colors.end, fs->packet_count);
ds_put_format(string, "%sn_bytes=%s%"PRIu64", ", ds_put_format(string, "%sn_bytes=%s%"PRIu64", ",
colors.param, colors.end, fs->byte_count); colors.param, colors.end, fs->byte_count);
}
if (fs->idle_timeout != OFP_FLOW_PERMANENT) { if (fs->idle_timeout != OFP_FLOW_PERMANENT) {
ds_put_format(string, "%sidle_timeout=%s%"PRIu16", ", ds_put_format(string, "%sidle_timeout=%s%"PRIu16", ",
colors.param, colors.end, fs->idle_timeout); 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", ", ds_put_format(string, "%simportance=%s%"PRIu16", ",
colors.param, colors.end, fs->importance); 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, ", ds_put_format(string, "%sidle_age=%s%d, ",
colors.param, colors.end, fs->idle_age); 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, ", ds_put_format(string, "%shard_age=%s%d, ",
colors.param, colors.end, fs->hard_age); 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); match_format(&fs->match, port_map, string, fs->priority);
if (string->string[string->length - 1] != ' ') { if (string->length != length) {
ds_put_char(string, ' '); ds_put_char(string, ' ');
} }
@ -1749,8 +1765,8 @@ ofp_print_flow_stats_reply(struct ds *string, const struct ofp_header *oh,
} }
break; break;
} }
ds_put_char(string, '\n'); ds_put_cstr(string, "\n ");
ofp_print_flow_stats(string, &fs, port_map); ofp_print_flow_stats(string, &fs, port_map, true);
} }
ofpbuf_uninit(&ofpacts); ofpbuf_uninit(&ofpacts);
} }

View File

@ -793,7 +793,7 @@ sbctl_dump_openflow(struct vconn *vconn, const struct uuid *uuid, bool stats)
ds_clear(&s); ds_clear(&s);
if (stats) { if (stats) {
ofp_print_flow_stats(&s, fs, NULL); ofp_print_flow_stats(&s, fs, NULL, true);
} else { } else {
ds_put_format(&s, "%stable=%s%"PRIu8" ", ds_put_format(&s, "%stable=%s%"PRIu8" ",
colors.special, colors.end, fs->table_id); colors.special, colors.end, fs->table_id);

View File

@ -1878,13 +1878,9 @@ trace_openflow(const struct ovntrace_flow *f, struct ovs_list *super)
struct ds s = DS_EMPTY_INITIALIZER; struct ds s = DS_EMPTY_INITIALIZER;
for (size_t i = 0; i < n_fses; i++) { for (size_t i = 0; i < n_fses; i++) {
ds_clear(&s); ds_clear(&s);
ofp_print_flow_stats(&s, &fses[i], NULL); ofp_print_flow_stats(&s, &fses[i], NULL, true);
ovntrace_node_append(super, OVNTRACE_NODE_ACTION,
/* ofp_print_flow_stats() indents its output with a space. "%s", ds_cstr(&s));
* Omit it. */
const char *p = ds_cstr(&s);
p += strspn(p, " ");
ovntrace_node_append(super, OVNTRACE_NODE_ACTION, "%s", p);
} }
ds_destroy(&s); ds_destroy(&s);
} else { } else {

View File

@ -212,9 +212,8 @@ AT_SETUP([bundle action with many ports])
AT_KEYWORDS([bundle_action]) AT_KEYWORDS([bundle_action])
OVS_VSWITCHD_START 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 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) 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 OVS_VSWITCHD_STOP
AT_CLEANUP AT_CLEANUP

View File

@ -132,10 +132,9 @@ mv stdout expout
AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual"], [0], [expout]) AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual"], [0], [expout])
# Check for the MAC learning entry. # Check for the MAC 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, vlan_tci=0x0000/0x0fff,dl_dst=50:54:00:00:00:05 actions=output:3
table=1, priority=0 actions=FLOOD 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. # 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. # 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: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, hard_timeout=60, vlan_tci=0x0000/0x0fff,dl_dst=50:54:00:00:00:06 actions=output:1
table=1, priority=0 actions=FLOOD table=1, priority=0 actions=FLOOD
NXST_FLOW reply:
]) ])
# Trace a packet arrival that updates the first learned MAC entry. # 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]) AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual"], [0], [expout])
# Check that the MAC learning entry was updated. # 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: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, hard_timeout=60, vlan_tci=0x0000/0x0fff,dl_dst=50:54:00:00:00:06 actions=output:1
table=1, priority=0 actions=FLOOD table=1, priority=0 actions=FLOOD
NXST_FLOW reply:
]) ])
OVS_VSWITCHD_STOP OVS_VSWITCHD_STOP
AT_CLEANUP AT_CLEANUP
@ -204,10 +201,9 @@ mv stdout expout
AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual"], [0], [expout]) AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual"], [0], [expout])
# Check that the MAC learning entry appeared. # 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, hard_timeout=10, dl_dst=50:54:00:00:00:07 actions=output:3
table=1, priority=0 actions=FLOOD table=1, priority=0 actions=FLOOD
NXST_FLOW reply:
]) ])
# For 25 seconds, make sure that the MAC learning entry doesn't # 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. # Make sure that 15 seconds without refreshing makes the flow time out.
ovs-appctl time/warp 15000 5000 ovs-appctl time/warp 15000 5000
sleep 1 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 table=1, priority=0 actions=FLOOD
NXST_FLOW reply:
]) ])
OVS_VSWITCHD_STOP OVS_VSWITCHD_STOP
AT_CLEANUP AT_CLEANUP
@ -265,9 +260,8 @@ mv stdout expout
AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual"], [0], [expout]) AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual"], [0], [expout])
# Check for the learning entry. # 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 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 OVS_VSWITCHD_STOP
AT_CLEANUP AT_CLEANUP
@ -293,10 +287,9 @@ mv stdout expout
AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual"], [0], [expout]) AT_CHECK([ovs-dpctl normalize-actions "$flow" "$actual"], [0], [expout])
# Check for the learning entry. # 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]] 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 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 OVS_VSWITCHD_STOP
AT_CLEANUP AT_CLEANUP
@ -508,9 +501,8 @@ OVS_VSWITCHD_START(
[add-port br0 p1 -- set Interface p1 type=dummy ofport_request=1]) [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-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-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], AT_CHECK([ovs-ofctl dump-flows br0 table=1 --no-stats], [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
table=1, dl_dst=50:54:00:00:00:05 actions=fin_timeout(idle_timeout=5,hard_timeout=10),output:1
]) ])
OVS_VSWITCHD_STOP OVS_VSWITCHD_STOP
AT_CLEANUP AT_CLEANUP
@ -528,65 +520,59 @@ cookie=0x123, table=2, reg0=0x5 actions=drop
cookie=0x234, table=1, reg0=0x6 actions=drop cookie=0x234, table=1, reg0=0x6 actions=drop
]) ])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt]) 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=0x3 actions=drop
cookie=0x123, table=1, reg0=0x4 actions=drop cookie=0x123, table=1, reg0=0x4 actions=drop
cookie=0x123, table=2, reg0=0x5 actions=drop cookie=0x123, table=2, reg0=0x5 actions=drop
cookie=0x234, table=1, reg0=0x6 actions=drop cookie=0x234, table=1, reg0=0x6 actions=drop
reg0=0x1 actions=learn(table=1,delete_learned,cookie=0x123) reg0=0x1 actions=learn(table=1,delete_learned,cookie=0x123)
reg0=0x2 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 # Delete one of the learn actions. The learned flows should stay, since there
# is another learn action with the identical target. # is another learn action with the identical target.
AT_CHECK([ovs-ofctl del-flows br0 'table=0 reg0=1']) 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=0x3 actions=drop
cookie=0x123, table=1, reg0=0x4 actions=drop cookie=0x123, table=1, reg0=0x4 actions=drop
cookie=0x123, table=2, reg0=0x5 actions=drop cookie=0x123, table=2, reg0=0x5 actions=drop
cookie=0x234, table=1, reg0=0x6 actions=drop cookie=0x234, table=1, reg0=0x6 actions=drop
reg0=0x2 actions=learn(table=1,delete_learned,cookie=0x123) 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 # Change the flow with the learn action by adding a second action. The learned
# flows should stay because the learn action is still there. # 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 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=0x3 actions=drop
cookie=0x123, table=1, reg0=0x4 actions=drop cookie=0x123, table=1, reg0=0x4 actions=drop
cookie=0x123, table=2, reg0=0x5 actions=drop cookie=0x123, table=2, reg0=0x5 actions=drop
cookie=0x234, table=1, reg0=0x6 actions=drop cookie=0x234, table=1, reg0=0x6 actions=drop
reg0=0x2 actions=output:1,learn(table=1,delete_learned,cookie=0x123) 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 # Change the flow with the learn action by replacing its learn action by one
# with a different target. The (previous) learned flows disappear. # 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 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=0x123, table=2, reg0=0x5 actions=drop
cookie=0x234, table=1, reg0=0x6 actions=drop cookie=0x234, table=1, reg0=0x6 actions=drop
reg0=0x2 actions=learn(table=1,delete_learned,cookie=0x234) 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 # 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. # 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 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=0x123, table=2, reg0=0x5 actions=drop
cookie=0x234, table=1, reg0=0x6 actions=drop cookie=0x234, table=1, reg0=0x6 actions=drop
reg0=0x2 actions=learn(table=1,delete_learned,cookie=0x234),output:2 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. # 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 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 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 # 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 del-flows br0])
AT_CHECK([ovs-ofctl add-flows br0 flows.txt]) 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=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=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) 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 cookie=0x567, table=5, reg0=0x8 actions=drop
reg0=0x1 actions=learn(table=1,delete_learned,cookie=0x123) reg0=0x1 actions=learn(table=1,delete_learned,cookie=0x123)
reg0=0x2 actions=learn(table=2,delete_learned,cookie=0x234) 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 # Deleting the flow with reg0=1 should cascade to delete a few levels
# of learned flows, but the ones with cookie=0x567 stick around # of learned flows, but the ones with cookie=0x567 stick around
# because of the flow with cookie=0x456. # because of the flow with cookie=0x456.
AT_CHECK([ovs-ofctl del-flows br0 'table=0 reg0=1']) 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=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=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=0x6 actions=drop
cookie=0x567, table=5, reg0=0x7 actions=drop cookie=0x567, table=5, reg0=0x7 actions=drop
cookie=0x567, table=5, reg0=0x8 actions=drop cookie=0x567, table=5, reg0=0x8 actions=drop
reg0=0x2 actions=learn(table=2,delete_learned,cookie=0x234) 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: # 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 del-flows br0 'table=0 reg0=2'])
AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl AT_CHECK([ovs-ofctl dump-flows br0 --no-stats | sort])
NXST_FLOW reply:
])
OVS_VSWITCHD_STOP OVS_VSWITCHD_STOP
AT_CLEANUP 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]) 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 cookie=0x1, table=1, dl_dst=50:54:00:00:00:01 actions=drop
NXST_FLOW reply:
]) ])
dnl Delete the learned flow dnl Delete the learned flow

View File

@ -222,8 +222,11 @@ syntax of \fIflows\fR. The output format is described in
.IP .IP
By default, \fBovs\-ofctl\fR prints flow entries in the same order By default, \fBovs\-ofctl\fR prints flow entries in the same order
that the switch sends them, which is unlikely to be intuitive or that the switch sends them, which is unlikely to be intuitive or
consistent. See the description of \fB\-\-sort\fR and \fB\-\-rsort\fR, consistent. Use \fB\-\-sort\fR and \fB\-\-rsort\fR to control display
under \fBOPTIONS\fR below, to influence the display order. 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 .TP
\fBdump\-aggregate \fIswitch \fR[\fIflows\fR] \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 name, \fBovs\-ofctl\fR refuses to display or accept the name, using
the number instead. 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" .IP "\fB\-\-read-only\fR"
Do not execute read/write commands. Do not execute read/write commands.
. .

View File

@ -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_accept_ports(void);
static bool should_show_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); static const struct ovs_cmdl_command *get_all_commands(void);
OVS_NO_RETURN static void usage(void); OVS_NO_RETURN static void usage(void);
@ -212,6 +215,8 @@ parse_options(int argc, char *argv[])
{"rsort", optional_argument, NULL, OPT_RSORT}, {"rsort", optional_argument, NULL, OPT_RSORT},
{"names", no_argument, &use_port_names, 1}, {"names", no_argument, &use_port_names, 1},
{"no-names", no_argument, &use_port_names, 0}, {"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}, {"unixctl", required_argument, NULL, OPT_UNIXCTL},
{"help", no_argument, NULL, 'h'}, {"help", no_argument, NULL, 'h'},
{"option", no_argument, NULL, 'o'}, {"option", no_argument, NULL, 'o'},
@ -1357,7 +1362,7 @@ compare_flows(const void *afs_, const void *bfs_)
static void static void
ofctl_dump_flows(struct ovs_cmdl_context *ctx) 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); ofctl_dump_flows__(ctx->argc, ctx->argv, false);
return; return;
} else { } else {
@ -1378,8 +1383,9 @@ ofctl_dump_flows(struct ovs_cmdl_context *ctx)
struct ds s = DS_EMPTY_INITIALIZER; struct ds s = DS_EMPTY_INITIALIZER;
for (size_t i = 0; i < n_fses; i++) { for (size_t i = 0; i < n_fses; i++) {
ds_clear(&s); ds_clear(&s);
ofp_print_flow_stats(&s, &fses[i], ports_to_show(ctx->argv[1])); ofp_print_flow_stats(&s, &fses[i], ports_to_show(ctx->argv[1]),
puts(ds_cstr(&s)); show_stats);
printf(" %s\n", ds_cstr(&s));
} }
ds_destroy(&s); ds_destroy(&s);