static struct ofport_dpif *
odp_port_to_ofport(const struct dpif_backer *, uint32_t odp_port);
+static void dpif_stats_update_hit_count(struct ofproto_dpif *ofproto,
+ uint64_t delta);
+
struct ofproto_dpif {
struct hmap_node all_ofproto_dpifs_node; /* In 'all_ofproto_dpifs'. */
struct ofproto up;
struct sset ghost_ports; /* Ports with no datapath port. */
struct sset port_poll_set; /* Queued names for port_poll() reply. */
int port_poll_errno; /* Last errno for port_poll() reply. */
+
+ /* Per ofproto's dpif stats. */
+ uint64_t n_hit;
+ uint64_t n_missed;
};
/* Defer flow mod completion until "ovs-appctl ofproto/unclog"? (Useful only
error = add_internal_flows(ofproto);
ofproto->up.tables[TBL_INTERNAL].flags = OFTABLE_HIDDEN | OFTABLE_READONLY;
+ ofproto->n_hit = 0;
+ ofproto->n_missed = 0;
+
return error;
}
if (error) {
continue;
}
+
+ ofproto->n_missed++;
flow_extract(upcall->packet, flow.skb_priority, flow.skb_mark,
&flow.tunnel, flow.in_port, &miss->flow);
* avoided by calling update_stats() whenever rules are created or
* deleted. However, the performance impact of making so many calls to the
* datapath do not justify the benefit of having perfectly accurate statistics.
+ *
+ * In addition, this function maintains per ofproto flow hit counts. The patch
+ * port is not treated specially. e.g. A packet ingress from br0 patched into
+ * br1 will increase the hit count of br0 by 1, however, does not affect
+ * the hit or miss counts of br1.
*/
static void
update_stats(struct dpif_backer *backer)
subfacet = subfacet_find(ofproto, key, key_len, key_hash);
switch (subfacet ? subfacet->path : SF_NOT_INSTALLED) {
case SF_FAST_PATH:
+ /* Update ofproto_dpif's hit count. */
+ if (stats->n_packets > subfacet->dp_packet_count) {
+ uint64_t delta = stats->n_packets - subfacet->dp_packet_count;
+ dpif_stats_update_hit_count(ofproto, delta);
+ }
+
update_subfacet_stats(subfacet, stats);
break;
/* If 'struct flow' gets additional metadata, we'll need to zero it out
* before traversing a patch port. */
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 19);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 20);
if (!ofport) {
xlate_report(ctx, "Nonexistent output port");
ctx->flow.nw_tos |= pdscp->dscp;
}
- odp_port = ofp_port_to_odp_port(ctx->ofproto, ofp_port);
if (ofport->tnl_port) {
odp_port = tnl_port_send(ofport->tnl_port, &ctx->flow);
if (odp_port == OVSP_NONE) {
commit_odp_tunnel_action(&ctx->flow, &ctx->base_flow,
ctx->odp_actions);
} else {
+ odp_port = ofport->odp_port;
out_port = vsp_realdev_to_vlandev(ctx->ofproto, odp_port,
ctx->flow.vlan_tci);
if (out_port != odp_port) {
ctx->flow.vlan_tci = htons(0);
}
+ ctx->flow.skb_mark &= ~IPSEC_MARK;
}
commit_odp_actions(&ctx->flow, &ctx->base_flow, ctx->odp_actions);
nl_msg_put_u32(ctx->odp_actions, OVS_ACTION_ATTR_OUTPUT, out_port);
tc = (ctx->flow.nw_tos & IP_DSCP_MASK) >> 2;
ttl = ctx->flow.nw_ttl ? ctx->flow.nw_ttl : 0x40;
ctx->flow.mpls_lse = set_mpls_lse_values(ttl, tc, 1, label);
- ctx->flow.encap_dl_type = ctx->flow.dl_type;
ctx->flow.mpls_depth = 1;
}
ctx->flow.dl_type = eth_type;
ctx->flow.mpls_lse = htonl(0);
if (!ctx->flow.mpls_depth) {
ctx->flow.dl_type = eth_type;
- ctx->flow.encap_dl_type = htons(0);
}
}
}
break;
case OFPACT_SET_IPV4_SRC:
- ctx->flow.nw_src = ofpact_get_SET_IPV4_SRC(a)->ipv4;
+ if (ctx->flow.dl_type == htons(ETH_TYPE_IP)) {
+ ctx->flow.nw_src = ofpact_get_SET_IPV4_SRC(a)->ipv4;
+ }
break;
case OFPACT_SET_IPV4_DST:
- ctx->flow.nw_dst = ofpact_get_SET_IPV4_DST(a)->ipv4;
+ if (ctx->flow.dl_type == htons(ETH_TYPE_IP)) {
+ ctx->flow.nw_dst = ofpact_get_SET_IPV4_DST(a)->ipv4;
+ }
break;
case OFPACT_SET_IPV4_DSCP:
break;
case OFPACT_SET_L4_SRC_PORT:
- ctx->flow.tp_src = htons(ofpact_get_SET_L4_SRC_PORT(a)->port);
+ if (is_ip_any(&ctx->flow)) {
+ ctx->flow.tp_src = htons(ofpact_get_SET_L4_SRC_PORT(a)->port);
+ }
break;
case OFPACT_SET_L4_DST_PORT:
- ctx->flow.tp_dst = htons(ofpact_get_SET_L4_DST_PORT(a)->port);
+ if (is_ip_any(&ctx->flow)) {
+ ctx->flow.tp_dst = htons(ofpact_get_SET_L4_DST_PORT(a)->port);
+ }
break;
case OFPACT_RESUBMIT:
static void
show_dp_format(const struct ofproto_dpif *ofproto, struct ds *ds)
{
- struct dpif_dp_stats s;
const struct shash_node **ports;
int i;
- dpif_get_dp_stats(ofproto->backer->dpif, &s);
-
ds_put_format(ds, "%s (%s):\n", ofproto->up.name,
dpif_name(ofproto->backer->dpif));
- /* xxx It would be better to show bridge-specific stats instead
- * xxx of dp ones. */
ds_put_format(ds,
- "\tlookups: hit:%"PRIu64" missed:%"PRIu64" lost:%"PRIu64"\n",
- s.n_hit, s.n_missed, s.n_lost);
+ "\tlookups: hit:%"PRIu64" missed:%"PRIu64"\n",
+ ofproto->n_hit, ofproto->n_missed);
ds_put_format(ds, "\tflows: %zu\n",
hmap_count(&ofproto->subfacets));
}
}
+static void
+dpif_stats_update_hit_count(struct ofproto_dpif *ofproto, uint64_t delta)
+{
+ ofproto->n_hit += delta;
+}
+
const struct ofproto_class ofproto_dpif_class = {
init,
enumerate_types,