* dpif_execute().
*
* - Do include packets and bytes that were obtained from the datapath
- * when a flow was deleted (e.g. dpif_flow_del()) or when its
- * statistics were reset (e.g. dpif_flow_put() with
+ * when its statistics were reset (e.g. dpif_flow_put() with
* DPIF_FP_ZERO_STATS).
- *
- * - Do not include any packets or bytes that can currently be obtained
- * from the datapath by, e.g., dpif_flow_get().
*/
uint64_t packet_count; /* Number of packets received. */
uint64_t byte_count; /* Number of bytes received. */
uint64_t rs_byte_count; /* Bytes pushed to resubmit children. */
long long int rs_used; /* Used time pushed to resubmit children. */
- /* Number of bytes passed to account_cb. This may include bytes that can
- * currently obtained from the datapath (thus, it can be greater than
- * byte_count). */
- uint64_t accounted_bytes;
+ uint64_t accounted_bytes; /* Bytes processed by facet_account(). */
struct hmap_node hmap_node; /* In owning ofproto's 'facets' hmap. */
struct list list_node; /* In owning rule's 'facets' list. */
long long int used);
static void facet_update_stats(struct ofproto_dpif *, struct facet *,
const struct dpif_flow_stats *);
+static void facet_reset_counters(struct facet *);
static void facet_reset_dp_stats(struct facet *, struct dpif_flow_stats *);
static void facet_push_stats(struct facet *);
-static void facet_account(struct ofproto_dpif *, struct facet *,
- uint64_t extra_bytes);
+static void facet_account(struct ofproto_dpif *, struct facet *);
static bool facet_is_controller_flow(struct facet *);
facet->dp_byte_count = stats->n_bytes;
facet_update_time(p, facet, stats->used);
- facet_account(p, facet, stats->n_bytes);
+ facet_account(p, facet);
facet_push_stats(facet);
} else {
/* There's a flow in the datapath that we know nothing about.
}
static void
-facet_account(struct ofproto_dpif *ofproto,
- struct facet *facet, uint64_t extra_bytes)
+facet_account(struct ofproto_dpif *ofproto, struct facet *facet)
{
- uint64_t total_bytes, n_bytes;
+ uint64_t n_bytes;
struct ofbundle *in_bundle;
const struct nlattr *a;
tag_type dummy = 0;
ovs_be16 vlan_tci;
int vlan;
- total_bytes = facet->byte_count + extra_bytes;
- if (total_bytes <= facet->accounted_bytes) {
+ if (facet->byte_count <= facet->accounted_bytes) {
return;
}
- n_bytes = total_bytes - facet->accounted_bytes;
- facet->accounted_bytes = total_bytes;
+ n_bytes = facet->byte_count - facet->accounted_bytes;
+ facet->accounted_bytes = facet->byte_count;
/* Test that 'tags' is nonzero to ensure that only flows that include an
* OFPP_NORMAL action are used for learning and bond slave rebalancing.
assert(!facet->dp_packet_count);
facet_push_stats(facet);
- facet_account(ofproto, facet, 0);
+ facet_account(ofproto, facet);
if (ofproto->netflow && !facet_is_controller_flow(facet)) {
struct ofexpired expired;
/* Reset counters to prevent double counting if 'facet' ever gets
* reinstalled. */
- facet->packet_count = 0;
- facet->byte_count = 0;
- facet->rs_packet_count = 0;
- facet->rs_byte_count = 0;
- facet->accounted_bytes = 0;
+ facet_reset_counters(facet);
netflow_flow_clear(&facet->nf_flow);
}
}
}
+static void
+facet_reset_counters(struct facet *facet)
+{
+ facet->packet_count = 0;
+ facet->byte_count = 0;
+ facet->rs_packet_count = 0;
+ facet->rs_byte_count = 0;
+ facet->accounted_bytes = 0;
+}
+
static void
facet_push_stats(struct facet *facet)
{
rule->facets = victim->facets;
list_moved(&rule->facets);
LIST_FOR_EACH (facet, list_node, &rule->facets) {
+ /* XXX: We're only clearing our local counters here. It's possible
+ * that quite a few packets are unaccounted for in the datapath
+ * statistics. These will be accounted to the new rule instead of
+ * cleared as required. This could be fixed by clearing out the
+ * datapath statistics for this facet, but currently it doesn't
+ * seem worth it. */
+ facet_reset_counters(facet);
facet->rule = rule;
}
} else {
}
}
+static void
+xlate_output_reg_action(struct action_xlate_ctx *ctx,
+ const struct nx_action_output_reg *naor)
+{
+ uint64_t ofp_port;
+
+ ofp_port = nxm_read_field_bits(naor->src, naor->ofs_nbits, &ctx->flow);
+
+ if (ofp_port <= UINT16_MAX) {
+ xlate_output_action__(ctx, ofp_port, ntohs(naor->max_len));
+ }
+}
+
static void
xlate_output_action(struct action_xlate_ctx *ctx,
const struct ofp_action_output *oao)
const struct nx_action_multipath *nam;
const struct nx_action_autopath *naa;
const struct nx_action_bundle *nab;
+ const struct nx_action_output_reg *naor;
enum ofputil_action_code code;
ovs_be64 tun_id;
bundle_execute_load(nab, &ctx->flow, slave_enabled_cb,
ctx->ofproto);
break;
+
+ case OFPUTIL_NXAST_OUTPUT_REG:
+ naor = (const struct nx_action_output_reg *) ia;
+ xlate_output_reg_action(ctx, naor);
+ break;
}
}
}
ds_put_char(result, '\n');
}
+static void
+trace_format_regs(struct ds *result, int level, const char *title,
+ struct ofproto_trace *trace)
+{
+ size_t i;
+
+ ds_put_char_multiple(result, '\t', level);
+ ds_put_format(result, "%s:", title);
+ for (i = 0; i < FLOW_N_REGS; i++) {
+ ds_put_format(result, " reg%zu=0x%"PRIx32, i, trace->flow.regs[i]);
+ }
+ ds_put_char(result, '\n');
+}
+
static void
trace_resubmit(struct action_xlate_ctx *ctx, struct rule_dpif *rule)
{
ds_put_char(result, '\n');
trace_format_flow(result, ctx->recurse + 1, "Resubmitted flow", trace);
+ trace_format_regs(result, ctx->recurse + 1, "Resubmitted regs", trace);
trace_format_rule(result, ctx->table_id, ctx->recurse + 1, rule);
}