@@ -81,6 +81,8 @@ v2.12.0 - 03 Sep 2019
* Add support for conntrack zone-based timeout policy.
- 'ovs-dpctl dump-flows' is no longer suitable for dumping offloaded flows.
'ovs-appctl dpctl/dump-flows' should be used instead.
+ - Add new argument '-m' for command 'ovs-appctl bridge/dump-flows',
+ so it can display offloaded packets statistics.
- Add L2 GRE tunnel over IPv6 support.
v2.11.0 - 19 Feb 2019
@@ -492,6 +492,8 @@ void dpif_port_poll_wait(const struct dpif *);
struct dpif_flow_stats {
uint64_t n_packets;
uint64_t n_bytes;
+ uint64_t n_offload_packets;
+ uint64_t n_offload_bytes;
long long int used;
uint16_t tcp_flags;
};
@@ -947,12 +947,15 @@ bond_recirculation_account(struct bond *bond)
if (rule) {
uint64_t n_packets OVS_UNUSED;
+ uint64_t n_offload_packets OVS_UNUSED;
long long int used OVS_UNUSED;
uint64_t n_bytes;
+ uint64_t n_offload_bytes;
rule->ofproto->ofproto_class->rule_get_stats(
- rule, &n_packets, &n_bytes, &used);
- bond_entry_account(entry, n_bytes);
+ rule, &n_packets, &n_bytes, &n_offload_packets,
+ &n_offload_bytes, &used);
+ bond_entry_account(entry, n_bytes + n_offload_bytes);
}
}
}
@@ -2260,7 +2260,7 @@ static enum reval_result
revalidate_ukey(struct udpif *udpif, struct udpif_key *ukey,
const struct dpif_flow_stats *stats,
struct ofpbuf *odp_actions, uint64_t reval_seq,
- struct recirc_refs *recircs)
+ struct recirc_refs *recircs, bool offloaded)
OVS_REQUIRES(ukey->mutex)
{
bool need_revalidate = ukey->reval_seq != reval_seq;
@@ -2295,7 +2295,7 @@ revalidate_ukey(struct udpif *udpif, struct udpif_key *ukey,
/* Stats for deleted flows will be attributed upon flow deletion. Skip. */
if (result != UKEY_DELETE) {
- xlate_push_stats(ukey->xcache, &push);
+ xlate_push_stats(ukey->xcache, &push, offloaded);
ukey->stats = *stats;
ukey->reval_seq = reval_seq;
}
@@ -2408,7 +2408,7 @@ push_dp_ops(struct udpif *udpif, struct ukey_op *ops, size_t n_ops)
if (op->ukey) {
ovs_mutex_lock(&op->ukey->mutex);
if (op->ukey->xcache) {
- xlate_push_stats(op->ukey->xcache, push);
+ xlate_push_stats(op->ukey->xcache, push, false);
ovs_mutex_unlock(&op->ukey->mutex);
continue;
}
@@ -2685,7 +2685,7 @@ revalidate(struct revalidator *revalidator)
result = UKEY_DELETE;
} else {
result = revalidate_ukey(udpif, ukey, &f->stats, &odp_actions,
- reval_seq, &recircs);
+ reval_seq, &recircs, f->attrs.offloaded);
}
ukey->dump_seq = dump_seq;
@@ -2770,7 +2770,7 @@ revalidator_sweep__(struct revalidator *revalidator, bool purge)
COVERAGE_INC(revalidate_missed_dp_flow);
memset(&stats, 0, sizeof stats);
result = revalidate_ukey(udpif, ukey, &stats, &odp_actions,
- reval_seq, &recircs);
+ reval_seq, &recircs, false);
}
if (result != UKEY_KEEP) {
/* Clears 'recircs' if filled by revalidate_ukey(). */
@@ -90,7 +90,7 @@ xlate_cache_netdev(struct xc_entry *entry, const struct dpif_flow_stats *stats)
/* Push stats and perform side effects of flow translation. */
void
xlate_push_stats_entry(struct xc_entry *entry,
- struct dpif_flow_stats *stats)
+ struct dpif_flow_stats *stats, bool offloaded)
{
struct eth_addr dmac;
@@ -104,7 +104,7 @@ xlate_push_stats_entry(struct xc_entry *entry,
? 0 : stats->n_packets);
break;
case XC_RULE:
- rule_dpif_credit_stats(entry->rule, stats);
+ rule_dpif_credit_stats(entry->rule, stats, offloaded);
break;
case XC_BOND:
bond_account(entry->bond.bond, entry->bond.flow,
@@ -169,7 +169,7 @@ xlate_push_stats_entry(struct xc_entry *entry,
void
xlate_push_stats(struct xlate_cache *xcache,
- struct dpif_flow_stats *stats)
+ struct dpif_flow_stats *stats, bool offloaded)
{
if (!stats->n_packets) {
return;
@@ -178,7 +178,7 @@ xlate_push_stats(struct xlate_cache *xcache,
struct xc_entry *entry;
struct ofpbuf entries = xcache->entries;
XC_ENTRY_FOR_EACH (entry, &entries) {
- xlate_push_stats_entry(entry, stats);
+ xlate_push_stats_entry(entry, stats, offloaded);
}
}
@@ -142,8 +142,10 @@ struct xlate_cache {
void xlate_cache_init(struct xlate_cache *);
struct xlate_cache *xlate_cache_new(void);
struct xc_entry *xlate_cache_add_entry(struct xlate_cache *, enum xc_type);
-void xlate_push_stats_entry(struct xc_entry *, struct dpif_flow_stats *);
-void xlate_push_stats(struct xlate_cache *, struct dpif_flow_stats *);
+void xlate_push_stats_entry(struct xc_entry *, struct dpif_flow_stats *,
+ bool);
+void xlate_push_stats(struct xlate_cache *, struct dpif_flow_stats *,
+ bool);
void xlate_cache_clear_entry(struct xc_entry *);
void xlate_cache_clear(struct xlate_cache *);
void xlate_cache_uninit(struct xlate_cache *);
@@ -3697,7 +3697,7 @@ native_tunnel_output(struct xlate_ctx *ctx, const struct xport *xport,
*/
if (backup_resubmit_stats) {
struct dpif_flow_stats stats = *backup_resubmit_stats;
- xlate_push_stats(ctx->xin->xcache, &stats);
+ xlate_push_stats(ctx->xin->xcache, &stats, false);
}
xlate_cache_steal_entries(backup_xcache, ctx->xin->xcache);
@@ -4263,7 +4263,7 @@ xlate_recursively(struct xlate_ctx *ctx, struct rule_dpif *rule,
const struct rule_actions *actions;
if (ctx->xin->resubmit_stats) {
- rule_dpif_credit_stats(rule, ctx->xin->resubmit_stats);
+ rule_dpif_credit_stats(rule, ctx->xin->resubmit_stats, false);
}
ctx->resubmits++;
@@ -7589,7 +7589,7 @@ xlate_actions(struct xlate_in *xin, struct xlate_out *xout)
ctx.xin->resubmit_stats, &ctx.table_id,
flow->in_port.ofp_port, true, true, ctx.xin->xcache);
if (ctx.xin->resubmit_stats) {
- rule_dpif_credit_stats(ctx.rule, ctx.xin->resubmit_stats);
+ rule_dpif_credit_stats(ctx.rule, ctx.xin->resubmit_stats, false);
}
if (ctx.xin->xcache) {
struct xc_entry *entry;
@@ -81,6 +81,7 @@ COVERAGE_DEFINE(packet_in_overflow);
struct flow_miss;
static void rule_get_stats(struct rule *, uint64_t *packets, uint64_t *bytes,
+ uint64_t *offload_packets, uint64_t *offload_bytes,
long long int *used);
static struct rule_dpif *rule_dpif_cast(const struct rule *);
static void rule_expire(struct rule_dpif *, long long now);
@@ -4115,7 +4116,7 @@ ofproto_dpif_execute_actions__(struct ofproto_dpif *ofproto,
dpif_flow_stats_extract(flow, packet, time_msec(), &stats);
if (rule) {
- rule_dpif_credit_stats(rule, &stats);
+ rule_dpif_credit_stats(rule, &stats, false);
}
uint64_t odp_actions_stub[1024 / 8];
@@ -4169,27 +4170,33 @@ ofproto_dpif_execute_actions(struct ofproto_dpif *ofproto,
static void
rule_dpif_credit_stats__(struct rule_dpif *rule,
const struct dpif_flow_stats *stats,
- bool credit_counts)
+ bool credit_counts, bool offloaded)
OVS_REQUIRES(rule->stats_mutex)
{
if (credit_counts) {
- rule->stats.n_packets += stats->n_packets;
- rule->stats.n_bytes += stats->n_bytes;
+ if (offloaded) {
+ rule->stats.n_offload_packets += stats->n_packets;
+ rule->stats.n_offload_bytes += stats->n_bytes;
+ } else {
+ rule->stats.n_packets += stats->n_packets;
+ rule->stats.n_bytes += stats->n_bytes;
+ }
}
rule->stats.used = MAX(rule->stats.used, stats->used);
}
void
rule_dpif_credit_stats(struct rule_dpif *rule,
- const struct dpif_flow_stats *stats)
+ const struct dpif_flow_stats *stats, bool offloaded)
{
ovs_mutex_lock(&rule->stats_mutex);
if (OVS_UNLIKELY(rule->new_rule)) {
ovs_mutex_lock(&rule->new_rule->stats_mutex);
- rule_dpif_credit_stats__(rule->new_rule, stats, rule->forward_counts);
+ rule_dpif_credit_stats__(rule->new_rule, stats, rule->forward_counts,
+ offloaded);
ovs_mutex_unlock(&rule->new_rule->stats_mutex);
} else {
- rule_dpif_credit_stats__(rule, stats, true);
+ rule_dpif_credit_stats__(rule, stats, true, offloaded);
}
ovs_mutex_unlock(&rule->stats_mutex);
}
@@ -4641,16 +4648,20 @@ rule_destruct(struct rule *rule_)
static void
rule_get_stats(struct rule *rule_, uint64_t *packets, uint64_t *bytes,
+ uint64_t *offload_packets, uint64_t *offload_bytes,
long long int *used)
{
struct rule_dpif *rule = rule_dpif_cast(rule_);
ovs_mutex_lock(&rule->stats_mutex);
if (OVS_UNLIKELY(rule->new_rule)) {
- rule_get_stats(&rule->new_rule->up, packets, bytes, used);
+ rule_get_stats(&rule->new_rule->up, packets, bytes, offload_packets,
+ offload_bytes, used);
} else {
*packets = rule->stats.n_packets;
*bytes = rule->stats.n_bytes;
+ *offload_packets = rule->stats.n_offload_packets;
+ *offload_bytes = rule->stats.n_offload_bytes;
*used = rule->stats.used;
}
ovs_mutex_unlock(&rule->stats_mutex);
@@ -4814,7 +4825,7 @@ ofproto_dpif_xcache_execute(struct ofproto_dpif *ofproto,
case XC_GROUP:
case XC_TNL_NEIGH:
case XC_TUNNEL_HEADER:
- xlate_push_stats_entry(entry, stats);
+ xlate_push_stats_entry(entry, stats, false);
break;
default:
OVS_NOT_REACHED();
@@ -107,7 +107,7 @@ struct rule_dpif *rule_dpif_lookup_from_table(struct ofproto_dpif *,
struct xlate_cache *);
void rule_dpif_credit_stats(struct rule_dpif *,
- const struct dpif_flow_stats *);
+ const struct dpif_flow_stats *, bool);
void rule_set_recirc_id(struct rule *, uint32_t id);
@@ -1349,7 +1349,10 @@ struct ofproto_class {
* in '*byte_count'. UINT64_MAX indicates that the packet count or byte
* count is unknown. */
void (*rule_get_stats)(struct rule *rule, uint64_t *packet_count,
- uint64_t *byte_count, long long int *used)
+ uint64_t *byte_count,
+ uint64_t *offload_packet_count,
+ uint64_t *offload_byte_count,
+ long long int *used)
/* OVS_EXCLUDED(ofproto_mutex) */;
/* Translates actions in 'opo->ofpacts', for 'opo->packet' in flow tables
@@ -4638,6 +4638,7 @@ handle_flow_stats_request(struct ofconn *ofconn,
ofpmp_init(&replies, request);
struct rule *rule;
RULE_COLLECTION_FOR_EACH (rule, &rules) {
+ uint64_t packet_count, byte_count;
long long int now = time_msec();
struct ofputil_flow_stats fs;
long long int created, used, modified;
@@ -4656,7 +4657,10 @@ handle_flow_stats_request(struct ofconn *ofconn,
ovs_mutex_unlock(&rule->mutex);
ofproto->ofproto_class->rule_get_stats(rule, &fs.packet_count,
- &fs.byte_count, &used);
+ &fs.byte_count, &packet_count,
+ &byte_count, &used);
+ fs.packet_count += packet_count;
+ fs.byte_count += byte_count;
minimatch_expand(&rule->cr.match, &fs.match);
fs.table_id = rule->table_id;
@@ -4681,14 +4685,19 @@ handle_flow_stats_request(struct ofconn *ofconn,
}
static void
-flow_stats_ds(struct ofproto *ofproto, struct rule *rule, struct ds *results)
+flow_stats_ds(struct ofproto *ofproto, struct rule *rule, struct ds *results,
+ bool verbosity)
{
uint64_t packet_count, byte_count;
+ uint64_t offload_packet_count, offload_byte_count;
const struct rule_actions *actions;
long long int created, used;
rule->ofproto->ofproto_class->rule_get_stats(rule, &packet_count,
- &byte_count, &used);
+ &byte_count,
+ &offload_packet_count,
+ &offload_byte_count,
+ &used);
ovs_mutex_lock(&rule->mutex);
actions = rule_get_actions(rule);
@@ -4699,8 +4708,18 @@ flow_stats_ds(struct ofproto *ofproto, struct rule *rule, struct ds *results)
ds_put_format(results, "table_id=%"PRIu8", ", rule->table_id);
}
ds_put_format(results, "duration=%llds, ", (time_msec() - created) / 1000);
- ds_put_format(results, "n_packets=%"PRIu64", ", packet_count);
- ds_put_format(results, "n_bytes=%"PRIu64", ", byte_count);
+ if (verbosity) {
+ ds_put_format(results, "n_packets=%"PRIu64", ", packet_count);
+ ds_put_format(results, "n_bytes=%"PRIu64", ", byte_count);
+ ds_put_format(results, "n_offload_packets=%"PRIu64", ",
+ offload_packet_count);
+ ds_put_format(results, "n_offload_bytes=%"PRIu64", ", offload_byte_count);
+ } else {
+ ds_put_format(results, "n_packets=%"PRIu64", ",
+ packet_count + offload_packet_count);
+ ds_put_format(results, "n_bytes=%"PRIu64", ",
+ byte_count + offload_packet_count);
+ }
cls_rule_format(&rule->cr, ofproto_get_tun_tab(ofproto), NULL, results);
ds_put_char(results, ',');
@@ -4714,7 +4733,7 @@ flow_stats_ds(struct ofproto *ofproto, struct rule *rule, struct ds *results)
/* Adds a pretty-printed description of all flows to 'results', including
* hidden flows (e.g., set up by in-band control). */
void
-ofproto_get_all_flows(struct ofproto *p, struct ds *results)
+ofproto_get_all_flows(struct ofproto *p, struct ds *results, bool verbosity)
{
struct oftable *table;
@@ -4722,7 +4741,7 @@ ofproto_get_all_flows(struct ofproto *p, struct ds *results)
struct rule *rule;
CLS_FOR_EACH (rule, cr, &table->cls) {
- flow_stats_ds(p, rule, results);
+ flow_stats_ds(p, rule, results, verbosity);
}
}
}
@@ -4810,23 +4829,28 @@ handle_aggregate_stats_request(struct ofconn *ofconn,
struct rule *rule;
RULE_COLLECTION_FOR_EACH (rule, &rules) {
- uint64_t packet_count;
- uint64_t byte_count;
+ uint64_t packet_count, offload_packet_count;
+ uint64_t byte_count, offload_byte_count;
long long int used;
ofproto->ofproto_class->rule_get_stats(rule, &packet_count,
- &byte_count, &used);
+ &byte_count,
+ &offload_packet_count,
+ &offload_byte_count,
+ &used);
if (packet_count == UINT64_MAX) {
unknown_packets = true;
} else {
stats.packet_count += packet_count;
+ stats.packet_count += offload_packet_count;
}
if (byte_count == UINT64_MAX) {
unknown_bytes = true;
} else {
stats.byte_count += byte_count;
+ stats.byte_count += offload_byte_count;
}
stats.flow_count++;
@@ -6017,6 +6041,7 @@ ofproto_rule_send_removed(struct rule *rule)
{
struct ofputil_flow_removed fr;
long long int used;
+ uint64_t offload_packet_count, offload_byte_count;
minimatch_expand(&rule->cr.match, &fr.match);
fr.priority = rule->cr.priority;
@@ -6040,7 +6065,12 @@ ofproto_rule_send_removed(struct rule *rule)
fr.hard_timeout = rule->hard_timeout;
ovs_mutex_unlock(&rule->mutex);
rule->ofproto->ofproto_class->rule_get_stats(rule, &fr.packet_count,
- &fr.byte_count, &used);
+ &fr.byte_count,
+ &offload_packet_count,
+ &offload_byte_count,
+ &used);
+ fr.packet_count += offload_packet_count;
+ fr.byte_count += offload_byte_count;
connmgr_send_flow_removed(connmgr, &fr);
ovs_mutex_unlock(&ofproto_mutex);
}
@@ -8850,11 +8880,13 @@ rule_eviction_priority(struct ofproto *ofproto, struct rule *rule)
expiration = modified + rule->hard_timeout * 1000;
}
if (rule->idle_timeout) {
- uint64_t packets, bytes;
+ uint64_t packets, bytes, offload_packets, offload_bytes OVS_UNUSED;
long long int used;
long long int idle_expiration;
- ofproto->ofproto_class->rule_get_stats(rule, &packets, &bytes, &used);
+ ofproto->ofproto_class->rule_get_stats(rule, &packets, &bytes,
+ &offload_packets,
+ &offload_bytes, &used);
idle_expiration = used + rule->idle_timeout * 1000;
expiration = MIN(expiration, idle_expiration);
}
@@ -541,7 +541,7 @@ void ofproto_configure_table(struct ofproto *, int table_id,
/* Configuration querying. */
bool ofproto_has_snoops(const struct ofproto *);
void ofproto_get_snoops(const struct ofproto *, struct sset *);
-void ofproto_get_all_flows(struct ofproto *p, struct ds *);
+void ofproto_get_all_flows(struct ofproto *p, struct ds *, bool);
void ofproto_get_netflow_ids(const struct ofproto *,
uint8_t *engine_type, uint8_t *engine_id);
@@ -514,7 +514,7 @@ bridge_init(const char *remote)
qos_unixctl_show_types, NULL);
unixctl_command_register("qos/show", "interface", 1, 1,
qos_unixctl_show, NULL);
- unixctl_command_register("bridge/dump-flows", "bridge", 1, 1,
+ unixctl_command_register("bridge/dump-flows", "[-m] bridge", 1, 2,
bridge_unixctl_dump_flows, NULL);
unixctl_command_register("bridge/reconnect", "[bridge]", 0, 1,
bridge_unixctl_reconnect, NULL);
@@ -3573,20 +3573,27 @@ bridge_lookup(const char *name)
/* Handle requests for a listing of all flows known by the OpenFlow
* stack, including those normally hidden. */
static void
-bridge_unixctl_dump_flows(struct unixctl_conn *conn, int argc OVS_UNUSED,
+bridge_unixctl_dump_flows(struct unixctl_conn *conn, int argc,
const char *argv[], void *aux OVS_UNUSED)
{
struct bridge *br;
struct ds results;
- br = bridge_lookup(argv[1]);
+ br = bridge_lookup(argv[argc - 1]);
if (!br) {
unixctl_command_reply_error(conn, "Unknown bridge");
return;
}
+ bool verbosity = false;
+ for (int i = 1; i < argc - 1; i++) {
+ if (!strcmp(argv[i], "-m")) {
+ verbosity = true;
+ }
+ }
+
ds_init(&results);
- ofproto_get_all_flows(br->ofproto, &results);
+ ofproto_get_all_flows(br->ofproto, &results, verbosity);
unixctl_command_reply(conn, ds_cstr(&results));
ds_destroy(&results);
Add argument '-m' for command ovs-appctl bridge/dump-flows to display the offloaded packets statistics. The commands display as below: orignal command: ovs-appctl bridge/dump-flows br0 duration=243589s, n_packets=214752, n_bytes=223673384, priority=0,actions=NORMAL table_id=254, duration=243589s, n_packets=0, n_bytes=0, n_offload_packets=0, n_offload_bytes=0, priority=2,recirc_id=0,actions=drop table_id=254, duration=243589s, n_packets=0, n_bytes=0, n_offload_packets=0, n_offload_bytes=0, priority=0,reg0=0x1,actions=controller(reason=) table_id=254, duration=243589s, n_packets=0, n_bytes=0, n_offload_packets=0, n_offload_bytes=0, priority=0,reg0=0x2,actions=drop table_id=254, duration=243589s, n_packets=0, n_bytes=0, n_offload_packets=0, n_offload_bytes=0, priority=0,reg0=0x3,actions=drop new command with argument '-m' ovs-appctl bridge/dump-flows -m br0 duration=243589s, n_packets=140, n_bytes=69284, n_offload_packets=214612, n_offload_bytes=223604100, priority=0,actions=NORMAL table_id=254, duration=243589s, n_packets=0, n_bytes=0, n_offload_packets=0, n_offload_bytes=0, priority=2,recirc_id=0,actions=drop table_id=254, duration=243589s, n_packets=0, n_bytes=0, n_offload_packets=0, n_offload_bytes=0, priority=0,reg0=0x1,actions=controller(reason=) table_id=254, duration=243589s, n_packets=0, n_bytes=0, n_offload_packets=0, n_offload_bytes=0, priority=0,reg0=0x2,actions=drop table_id=254, duration=243589s, n_packets=0, n_bytes=0, n_offload_packets=0, n_offload_bytes=0, priority=0,reg0=0x3,actions=drop Signed-off-by: zhaozhanxu <zhaozhanxu@163.com> --- NEWS | 2 ++ lib/dpif.h | 2 ++ ofproto/bond.c | 7 +++-- ofproto/ofproto-dpif-upcall.c | 10 +++---- ofproto/ofproto-dpif-xlate-cache.c | 8 +++--- ofproto/ofproto-dpif-xlate-cache.h | 6 ++-- ofproto/ofproto-dpif-xlate.c | 6 ++-- ofproto/ofproto-dpif.c | 29 +++++++++++++------ ofproto/ofproto-dpif.h | 2 +- ofproto/ofproto-provider.h | 5 +++- ofproto/ofproto.c | 58 +++++++++++++++++++++++++++++--------- ofproto/ofproto.h | 2 +- vswitchd/bridge.c | 15 +++++++--- 13 files changed, 107 insertions(+), 45 deletions(-)