When verbose mode tuned on, all dp flow fields described by the netlink attributes are displayed, including fully wildcarded attributes. Otherwise, the fully wildcarded attributes are omitted for brevity.
Added -m option to "ovs-dpctl dump-flows" to enable verbose mode. It is off by default. Signed-off-by: Andy Zhou <az...@nicira.com> --- lib/dpif.c | 2 +- lib/odp-util.c | 47 ++++++++++++++++++++++++++++++++++------------- lib/odp-util.h | 2 +- ofproto/ofproto-dpif.c | 2 +- tests/odp.at | 2 +- tests/ofproto-dpif.at | 18 +++++++++--------- tests/test-odp.c | 2 +- utilities/ovs-dpctl.c | 4 ++-- 8 files changed, 50 insertions(+), 29 deletions(-) diff --git a/lib/dpif.c b/lib/dpif.c index 3d6aed7..ae4da62 100644 --- a/lib/dpif.c +++ b/lib/dpif.c @@ -1351,7 +1351,7 @@ log_flow_message(const struct dpif *dpif, int error, const char *operation, if (error) { ds_put_format(&ds, "(%s) ", ovs_strerror(error)); } - odp_flow_format(key, key_len, mask, mask_len, &ds); + odp_flow_format(key, key_len, mask, mask_len, &ds, true); if (stats) { ds_put_cstr(&ds, ", "); dpif_flow_stats_format(stats, &ds); diff --git a/lib/odp-util.c b/lib/odp-util.c index 50b7e81..cc83fa5 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -51,7 +51,8 @@ static const char *delimiters = ", \t\r\n"; static int parse_odp_key_mask_attr(const char *, const struct simap *port_names, struct ofpbuf *, struct ofpbuf *); static void format_odp_key_attr(const struct nlattr *a, - const struct nlattr *ma, struct ds *ds); + const struct nlattr *ma, struct ds *ds, + bool verbose); /* Returns one the following for the action with the given OVS_ACTION_ATTR_* * 'type': @@ -399,7 +400,7 @@ format_odp_action(struct ds *ds, const struct nlattr *a) break; case OVS_ACTION_ATTR_SET: ds_put_cstr(ds, "set("); - format_odp_key_attr(nl_attr_get(a), NULL, ds); + format_odp_key_attr(nl_attr_get(a), NULL, ds, true); ds_put_cstr(ds, ")"); break; case OVS_ACTION_ATTR_PUSH_VLAN: @@ -898,6 +899,12 @@ tun_key_to_attr(struct ofpbuf *a, const struct flow_tnl *tun_key) } static bool +odp_mask_attr_is_wildcard(const struct nlattr *ma) +{ + return is_all_zeros(nl_attr_get(ma), nl_attr_get_size(ma)); +} + +static bool odp_mask_attr_is_exact(const struct nlattr *ma) { bool is_exact = false; @@ -929,7 +936,7 @@ odp_mask_attr_is_exact(const struct nlattr *ma) static void format_odp_key_attr(const struct nlattr *a, const struct nlattr *ma, - struct ds *ds) + struct ds *ds, bool verbose) { struct flow_tnl tun_key; enum ovs_key_attr attr = nl_attr_type(a); @@ -972,9 +979,10 @@ format_odp_key_attr(const struct nlattr *a, const struct nlattr *ma, case OVS_KEY_ATTR_ENCAP: if (ma && nl_attr_get_size(ma) && nl_attr_get_size(a)) { odp_flow_format(nl_attr_get(a), nl_attr_get_size(a), - nl_attr_get(ma), nl_attr_get_size(ma), ds); + nl_attr_get(ma), nl_attr_get_size(ma), ds, verbose); } else if (nl_attr_get_size(a)) { - odp_flow_format(nl_attr_get(a), nl_attr_get_size(a), NULL, 0, ds); + odp_flow_format(nl_attr_get(a), nl_attr_get_size(a), NULL, 0, ds, + verbose); } break; @@ -1337,7 +1345,7 @@ generate_all_wildcard_mask(struct ofpbuf *ofp, const struct nlattr *key) void odp_flow_format(const struct nlattr *key, size_t key_len, const struct nlattr *mask, size_t mask_len, - struct ds *ds) + struct ds *ds, bool verbose) { if (key_len) { const struct nlattr *a; @@ -1345,22 +1353,35 @@ odp_flow_format(const struct nlattr *key, size_t key_len, bool has_ethtype_key = false; const struct nlattr *ma = NULL; struct ofpbuf ofp; + bool first_field = true; ofpbuf_init(&ofp, 100); NL_ATTR_FOR_EACH (a, left, key, key_len) { - if (a != key) { - ds_put_char(ds, ','); - } - if (nl_attr_type(a) == OVS_KEY_ATTR_ETHERTYPE) { + bool is_nested_attr; + bool is_wildcard = false; + int attr_type = nl_attr_type(a); + + if (attr_type == OVS_KEY_ATTR_ETHERTYPE) { has_ethtype_key = true; } + + is_nested_attr = (odp_flow_key_attr_len(attr_type) == -2); + if (mask && mask_len) { ma = nl_attr_find__(mask, mask_len, nl_attr_type(a)); - if (!ma) { + is_wildcard = ma ? odp_mask_attr_is_wildcard(ma) : true; + } + + if (verbose || !is_wildcard || is_nested_attr) { + if (is_wildcard && !ma) { ma = generate_all_wildcard_mask(&ofp, a); } + if (!first_field) { + ds_put_char(ds, ','); + } + format_odp_key_attr(a, ma, ds, verbose); + first_field = false; } - format_odp_key_attr(a, ma, ds); ofpbuf_clear(&ofp); } ofpbuf_uninit(&ofp); @@ -1395,7 +1416,7 @@ void odp_flow_key_format(const struct nlattr *key, size_t key_len, struct ds *ds) { - odp_flow_format(key, key_len, NULL, 0, ds); + odp_flow_format(key, key_len, NULL, 0, ds, true); } static void diff --git a/lib/odp-util.h b/lib/odp-util.h index 0c10cfa..7e27888 100644 --- a/lib/odp-util.h +++ b/lib/odp-util.h @@ -94,7 +94,7 @@ enum odp_key_fitness odp_tun_key_from_attr(const struct nlattr *, void odp_flow_format(const struct nlattr *key, size_t key_len, const struct nlattr *mask, size_t mask_len, - struct ds *); + struct ds *, bool verbose); void odp_flow_key_format(const struct nlattr *, size_t, struct ds *); int odp_flow_from_string(const char *s, const struct simap *port_names, diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index 68b455b..904bc11 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -6291,7 +6291,7 @@ ofproto_unixctl_dpif_dump_flows(struct unixctl_conn *conn, } odp_flow_format(subfacet->key, subfacet->key_len, - mask.data, mask.size, &ds); + mask.data, mask.size, &ds, false); ds_put_format(&ds, ", packets:%"PRIu64", bytes:%"PRIu64", used:", subfacet->dp_packet_count, subfacet->dp_byte_count); diff --git a/tests/odp.at b/tests/odp.at index 5776b95..b0aca6c 100644 --- a/tests/odp.at +++ b/tests/odp.at @@ -88,7 +88,7 @@ in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15),eth_type(0x1234/0xff in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15),eth_type(0x0800),ipv4(src=35.8.2.41/255.255.255.0,dst=172.16.0.20/255.255.255.0,proto=5/0xf0,tos=0x80/0xf0,ttl=128/0xf0,frag=no/0xf0) in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15),eth_type(0x0800),ipv4(src=35.8.2.41,dst=172.16.0.20,proto=6,tos=0,ttl=128,frag=no),tcp(src=80/0xff00,dst=8080/0xff) in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15),eth_type(0x0800),ipv4(src=35.8.2.41,dst=172.16.0.20,proto=17,tos=0,ttl=128,frag=no),udp(src=81/0xff00,dst=6632/0xff) -in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15),eth_type(0x0800),ipv4(src=35.8.2.41,dst=172.16.0.20,proto=17,tos=0,ttl=128,frag=no),udp(src=81/0,dst=6632/0) +in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15),eth_type(0x0800),ipv4(src=35.8.2.41,dst=172.16.0.20,proto=17,tos=0,ttl=128,frag=no),udp(src=81/0xff,dst=6632/0xff00) in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15),eth_type(0x0800),ipv4(src=35.8.2.41,dst=172.16.0.20,proto=1,tos=0,ttl=128,frag=no),icmp(type=1/0xf0,code=2/0xff) in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15),eth_type(0x86dd),ipv6(src=::1/::255,dst=::2/::255,label=0/0xf0,proto=10/0xf0,tclass=0x70/0xf0,hlimit=128/0xf0,frag=no/0xf0) in_port(1),eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15),eth_type(0x86dd),ipv6(src=::1,dst=::2,label=0,proto=6,tclass=0,hlimit=128,frag=no),tcp(src=80/0xff00,dst=8080/0xff) diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at index d5e5e3c..3d23404 100644 --- a/tests/ofproto-dpif.at +++ b/tests/ofproto-dpif.at @@ -2088,12 +2088,12 @@ AT_CHECK([ovs-appctl netdev-dummy/receive p2 'in_port(2),eth(src=50:54:00:00:00: AT_CHECK([ovs-appctl netdev-dummy/receive p3 'in_port(3),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)']) AT_CHECK([ovs-appctl dpif/dump-flows br0 | sort | STRIP_USED], [0], [dnl -in_port(1),eth(src=50:54:00:00:00:05/00:00:00:00:00:00,dst=50:54:00:00:00:07/00:00:00:00:00:00),eth_type(0x0800),ipv4(src=192.168.0.1/0.0.0.0,dst=192.168.0.2/0.0.0.0,proto=1/0,tos=0/0,ttl=64/0,frag=no/0xff),icmp(type=8/0,code=0/0), packets:0, bytes:0, used:0.0s, actions:userspace(pid=0,slow_path(controller)) -in_port(2),eth(src=50:54:00:00:00:07/00:00:00:00:00:00,dst=50:54:00:00:00:05/00:00:00:00:00:00),eth_type(0x0800),ipv4(src=192.168.0.2/0.0.0.0,dst=192.168.0.1/0.0.0.0,proto=1/0,tos=0/0,ttl=64/0,frag=no/0xff),icmp(type=0/0,code=0/0), packets:0, bytes:0, used:0.0s, actions:userspace(pid=0,slow_path(controller)) +in_port(1),eth_type(0x0800),ipv4(src=192.168.0.1/0.0.0.0,dst=192.168.0.2/0.0.0.0,proto=1/0,tos=0/0,ttl=64/0,frag=no/0xff), packets:0, bytes:0, used:0.0s, actions:userspace(pid=0,slow_path(controller)) +in_port(2),eth_type(0x0800),ipv4(src=192.168.0.2/0.0.0.0,dst=192.168.0.1/0.0.0.0,proto=1/0,tos=0/0,ttl=64/0,frag=no/0xff), packets:0, bytes:0, used:0.0s, actions:userspace(pid=0,slow_path(controller)) ]) AT_CHECK([ovs-appctl dpif/dump-flows br1 | sort | STRIP_USED], [0], [dnl -in_port(3),eth(src=50:54:00:00:00:09/00:00:00:00:00:00,dst=50:54:00:00:00:0a/00:00:00:00:00:00),eth_type(0x0800),ipv4(src=10.0.0.2/0.0.0.0,dst=10.0.0.1/0.0.0.0,proto=1/0,tos=0/0,ttl=64/0,frag=no/0xff),icmp(type=8/0,code=0/0), packets:0, bytes:0, used:0.0s, actions:userspace(pid=0,slow_path(controller)) +in_port(3),eth_type(0x0800),ipv4(src=10.0.0.2/0.0.0.0,dst=10.0.0.1/0.0.0.0,proto=1/0,tos=0/0,ttl=64/0,frag=no/0xff), packets:0, bytes:0, used:0.0s, actions:userspace(pid=0,slow_path(controller)) ]) OVS_VSWITCHD_STOP @@ -2110,12 +2110,12 @@ AT_CHECK([ovs-appctl netdev-dummy/receive p2 'in_port(2),eth(src=50:54:00:00:00: AT_CHECK([ovs-appctl netdev-dummy/receive p3 'in_port(3),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)']) AT_CHECK([ovs-appctl dpif/dump-flows br0 | sort | STRIP_USED], [0], [dnl -in_port(1),eth(src=50:54:00:00:00:05/00:00:00:00:00:00,dst=50:54:00:00:00:07/00:00:00:00:00:00),eth_type(0x0800),ipv4(src=192.168.0.1/0.0.0.0,dst=192.168.0.2/0.0.0.0,proto=1/0,tos=0/0,ttl=64/0,frag=no/0xff),icmp(type=8/0,code=0/0), packets:0, bytes:0, used:0.0s, actions:userspace(pid=0,slow_path(controller)) -in_port(2),eth(src=50:54:00:00:00:07/00:00:00:00:00:00,dst=50:54:00:00:00:05/00:00:00:00:00:00),eth_type(0x0800),ipv4(src=192.168.0.2/0.0.0.0,dst=192.168.0.1/0.0.0.0,proto=1/0,tos=0/0,ttl=64/0,frag=no/0xff),icmp(type=0/0,code=0/0), packets:0, bytes:0, used:0.0s, actions:userspace(pid=0,slow_path(controller)) +in_port(1),eth_type(0x0800),ipv4(src=192.168.0.1/0.0.0.0,dst=192.168.0.2/0.0.0.0,proto=1/0,tos=0/0,ttl=64/0,frag=no/0xff), packets:0, bytes:0, used:0.0s, actions:userspace(pid=0,slow_path(controller)) +in_port(2),eth_type(0x0800),ipv4(src=192.168.0.2/0.0.0.0,dst=192.168.0.1/0.0.0.0,proto=1/0,tos=0/0,ttl=64/0,frag=no/0xff), packets:0, bytes:0, used:0.0s, actions:userspace(pid=0,slow_path(controller)) ]) AT_CHECK([ovs-appctl dpif/dump-flows br1 | sort | STRIP_USED], [0], [dnl -in_port(3),eth(src=50:54:00:00:00:09/00:00:00:00:00:00,dst=50:54:00:00:00:0a/00:00:00:00:00:00),eth_type(0x0800),ipv4(src=10.0.0.2/0.0.0.0,dst=10.0.0.1/0.0.0.0,proto=1/0,tos=0/0,ttl=64/0,frag=no/0xff),icmp(type=8/0,code=0/0), packets:0, bytes:0, used:0.0s, actions:userspace(pid=0,slow_path(controller)) +in_port(3),eth_type(0x0800),ipv4(src=10.0.0.2/0.0.0.0,dst=10.0.0.1/0.0.0.0,proto=1/0,tos=0/0,ttl=64/0,frag=no/0xff), packets:0, bytes:0, used:0.0s, actions:userspace(pid=0,slow_path(controller)) ]) AT_CHECK([ovs-appctl dpif/del-flows br0]) @@ -2123,7 +2123,7 @@ AT_CHECK([ovs-appctl dpif/dump-flows br0 | sort | STRIP_USED], [0], [dnl ]) AT_CHECK([ovs-appctl dpif/dump-flows br1 | sort | STRIP_USED], [0], [dnl -in_port(3),eth(src=50:54:00:00:00:09/00:00:00:00:00:00,dst=50:54:00:00:00:0a/00:00:00:00:00:00),eth_type(0x0800),ipv4(src=10.0.0.2/0.0.0.0,dst=10.0.0.1/0.0.0.0,proto=1/0,tos=0/0,ttl=64/0,frag=no/0xff),icmp(type=8/0,code=0/0), packets:0, bytes:0, used:0.0s, actions:userspace(pid=0,slow_path(controller)) +in_port(3),eth_type(0x0800),ipv4(src=10.0.0.2/0.0.0.0,dst=10.0.0.1/0.0.0.0,proto=1/0,tos=0/0,ttl=64/0,frag=no/0xff), packets:0, bytes:0, used:0.0s, actions:userspace(pid=0,slow_path(controller)) ]) OVS_VSWITCHD_STOP @@ -2170,10 +2170,10 @@ dummy@ovs-dummy: hit:13 missed:2 ]) AT_CHECK([ovs-appctl dpif/dump-flows br0 | STRIP_USED], [0], [dnl -in_port(100),eth(src=50:54:00:00:00:05/00:00:00:00:00:00,dst=50:54:00:00:00:07/00:00:00:00:00:00),eth_type(0x0800),ipv4(src=192.168.0.1/0.0.0.0,dst=192.168.0.2/0.0.0.0,proto=1/0,tos=0/0,ttl=64/0,frag=no/0xff),icmp(type=8/0,code=0/0), packets:9, bytes:540, used:0.0s, actions:101,3,2 +in_port(100),eth_type(0x0800),ipv4(src=192.168.0.1/0.0.0.0,dst=192.168.0.2/0.0.0.0,proto=1/0,tos=0/0,ttl=64/0,frag=no/0xff), packets:9, bytes:540, used:0.0s, actions:101,3,2 ]), AT_CHECK([ovs-appctl dpif/dump-flows br1 | STRIP_USED], [0], [dnl -in_port(101),eth(src=50:54:00:00:00:07/00:00:00:00:00:00,dst=50:54:00:00:00:05/00:00:00:00:00:00),eth_type(0x0800),ipv4(src=192.168.0.2/0.0.0.0,dst=192.168.0.1/0.0.0.0,proto=1/0,tos=0/0,ttl=64/0,frag=no/0xff),icmp(type=8/0,code=0/0), packets:4, bytes:240, used:0.0s, actions:100,2,3 +in_port(101),eth_type(0x0800),ipv4(src=192.168.0.2/0.0.0.0,dst=192.168.0.1/0.0.0.0,proto=1/0,tos=0/0,ttl=64/0,frag=no/0xff), packets:4, bytes:240, used:0.0s, actions:100,2,3 ]) AT_CHECK([ovs-ofctl dump-ports br0 pbr0], [0], [dnl diff --git a/tests/test-odp.c b/tests/test-odp.c index b1d2853..45605e4 100644 --- a/tests/test-odp.c +++ b/tests/test-odp.c @@ -86,7 +86,7 @@ parse_keys(bool wc_keys) ds_init(&out); if (wc_keys) { odp_flow_format(odp_key.data, odp_key.size, - odp_mask.data, odp_mask.size, &out); + odp_mask.data, odp_mask.size, &out, false); } else { odp_flow_key_format(odp_key.data, odp_key.size, &out); } diff --git a/utilities/ovs-dpctl.c b/utilities/ovs-dpctl.c index fa78b53..42cb205 100644 --- a/utilities/ovs-dpctl.c +++ b/utilities/ovs-dpctl.c @@ -761,7 +761,7 @@ dpctl_dump_flows(int argc, char *argv[]) &mask, &mask_len, &actions, &actions_len, &stats)) { ds_clear(&ds); - odp_flow_format(key, key_len, mask, mask_len, &ds); + odp_flow_format(key, key_len, mask, mask_len, &ds, verbosity); ds_put_cstr(&ds, ", "); dpif_flow_stats_format(stats, &ds); @@ -1050,7 +1050,7 @@ dpctl_normalize_actions(int argc, char *argv[]) "odp_flow_key_from_string"); ds_clear(&s); - odp_flow_format(keybuf.data, keybuf.size, NULL, 0, &s); + odp_flow_format(keybuf.data, keybuf.size, NULL, 0, &s, verbosity); printf("input flow: %s\n", ds_cstr(&s)); run(odp_flow_key_to_flow(keybuf.data, keybuf.size, &flow), -- 1.7.9.5 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev