+ ofpbuf_delete(odp_actions);
+}
+
+/* Updates 'subfacet''s datapath flow, setting its actions to 'actions_len'
+ * bytes of actions in 'actions'. If 'stats' is non-null, statistics counters
+ * in the datapath will be zeroed and 'stats' will be updated with traffic new
+ * since 'subfacet' was last updated.
+ *
+ * Returns 0 if successful, otherwise a positive errno value. */
+static int
+subfacet_install(struct subfacet *subfacet,
+ const struct nlattr *actions, size_t actions_len,
+ struct dpif_flow_stats *stats)
+{
+ struct facet *facet = subfacet->facet;
+ struct ofproto_dpif *ofproto = ofproto_dpif_cast(facet->rule->up.ofproto);
+ struct odputil_keybuf keybuf;
+ enum dpif_flow_put_flags flags;
+ struct ofpbuf key;
+ int ret;
+
+ flags = DPIF_FP_CREATE | DPIF_FP_MODIFY;
+ if (stats) {
+ flags |= DPIF_FP_ZERO_STATS;
+ }
+
+ subfacet_get_key(subfacet, &keybuf, &key);
+ ret = dpif_flow_put(ofproto->dpif, flags, key.data, key.size,
+ actions, actions_len, stats);
+
+ if (stats) {
+ subfacet_reset_dp_stats(subfacet, stats);
+ }
+
+ return ret;
+}
+
+/* If 'subfacet' is installed in the datapath, uninstalls it. */
+static void
+subfacet_uninstall(struct subfacet *subfacet)
+{
+ if (subfacet->installed) {
+ struct rule_dpif *rule = subfacet->facet->rule;
+ struct ofproto_dpif *ofproto = ofproto_dpif_cast(rule->up.ofproto);
+ struct odputil_keybuf keybuf;
+ struct dpif_flow_stats stats;
+ struct ofpbuf key;
+ int error;
+
+ subfacet_get_key(subfacet, &keybuf, &key);
+ error = dpif_flow_del(ofproto->dpif, key.data, key.size, &stats);
+ subfacet_reset_dp_stats(subfacet, &stats);
+ if (!error) {
+ subfacet_update_stats(subfacet, &stats);
+ }
+ subfacet->installed = false;
+ } else {
+ assert(subfacet->dp_packet_count == 0);
+ assert(subfacet->dp_byte_count == 0);
+ }
+}
+
+/* Resets 'subfacet''s datapath statistics counters. This should be called
+ * when 'subfacet''s statistics are cleared in the datapath. If 'stats' is
+ * non-null, it should contain the statistics returned by dpif when 'subfacet'
+ * was reset in the datapath. 'stats' will be modified to include only
+ * statistics new since 'subfacet' was last updated. */
+static void
+subfacet_reset_dp_stats(struct subfacet *subfacet,
+ struct dpif_flow_stats *stats)
+{
+ if (stats
+ && subfacet->dp_packet_count <= stats->n_packets
+ && subfacet->dp_byte_count <= stats->n_bytes) {
+ stats->n_packets -= subfacet->dp_packet_count;
+ stats->n_bytes -= subfacet->dp_byte_count;
+ }
+
+ subfacet->dp_packet_count = 0;
+ subfacet->dp_byte_count = 0;
+}
+
+/* Updates 'subfacet''s used time. The caller is responsible for calling
+ * facet_push_stats() to update the flows which 'subfacet' resubmits into. */
+static void
+subfacet_update_time(struct subfacet *subfacet, long long int used)
+{
+ if (used > subfacet->used) {
+ subfacet->used = used;
+ facet_update_time(subfacet->facet, used);
+ }
+}
+
+/* Folds the statistics from 'stats' into the counters in 'subfacet'.
+ *
+ * Because of the meaning of a subfacet's counters, it only makes sense to do
+ * this if 'stats' are not tracked in the datapath, that is, if 'stats'
+ * represents a packet that was sent by hand or if it represents statistics
+ * that have been cleared out of the datapath. */
+static void
+subfacet_update_stats(struct subfacet *subfacet,
+ const struct dpif_flow_stats *stats)
+{
+ if (stats->n_packets || stats->used > subfacet->used) {
+ struct facet *facet = subfacet->facet;
+
+ subfacet_update_time(subfacet, stats->used);
+ facet->packet_count += stats->n_packets;
+ facet->byte_count += stats->n_bytes;
+ facet->tcp_flags |= stats->tcp_flags;
+ facet_push_stats(facet);
+ netflow_flow_update_flags(&facet->nf_flow, stats->tcp_flags);
+ }
+}
+\f
+/* Rules. */
+
+static struct rule_dpif *
+rule_dpif_lookup(struct ofproto_dpif *ofproto, const struct flow *flow,
+ uint8_t table_id)
+{
+ struct cls_rule *cls_rule;
+ struct classifier *cls;
+
+ if (table_id >= N_TABLES) {
+ return NULL;
+ }
+
+ cls = &ofproto->up.tables[table_id].cls;
+ if (flow->nw_frag & FLOW_NW_FRAG_ANY
+ && ofproto->up.frag_handling == OFPC_FRAG_NORMAL) {
+ /* For OFPC_NORMAL frag_handling, we must pretend that transport ports
+ * are unavailable. */
+ struct flow ofpc_normal_flow = *flow;
+ ofpc_normal_flow.tp_src = htons(0);
+ ofpc_normal_flow.tp_dst = htons(0);
+ cls_rule = classifier_lookup(cls, &ofpc_normal_flow);
+ } else {
+ cls_rule = classifier_lookup(cls, flow);
+ }
+ return rule_dpif_cast(rule_from_cls_rule(cls_rule));
+}
+
+static void
+complete_operation(struct rule_dpif *rule)
+{
+ struct ofproto_dpif *ofproto = ofproto_dpif_cast(rule->up.ofproto);
+
+ rule_invalidate(rule);
+ if (clogged) {
+ struct dpif_completion *c = xmalloc(sizeof *c);
+ c->op = rule->up.pending;
+ list_push_back(&ofproto->completions, &c->list_node);
+ } else {
+ ofoperation_complete(rule->up.pending, 0);
+ }
+}
+
+static struct rule *
+rule_alloc(void)
+{
+ struct rule_dpif *rule = xmalloc(sizeof *rule);
+ return &rule->up;
+}
+
+static void
+rule_dealloc(struct rule *rule_)
+{
+ struct rule_dpif *rule = rule_dpif_cast(rule_);
+ free(rule);
+}
+
+static enum ofperr
+rule_construct(struct rule *rule_)
+{
+ struct rule_dpif *rule = rule_dpif_cast(rule_);
+ struct ofproto_dpif *ofproto = ofproto_dpif_cast(rule->up.ofproto);
+ struct rule_dpif *victim;
+ uint8_t table_id;
+ enum ofperr error;
+
+ error = validate_actions(rule->up.actions, rule->up.n_actions,
+ &rule->up.cr.flow, ofproto->max_ports);
+ if (error) {
+ return error;
+ }
+
+ rule->packet_count = 0;
+ rule->byte_count = 0;
+
+ victim = rule_dpif_cast(ofoperation_get_victim(rule->up.pending));
+ if (victim && !list_is_empty(&victim->facets)) {
+ 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 {
+ /* Must avoid list_moved() in this case. */
+ list_init(&rule->facets);
+ }
+
+ table_id = rule->up.table_id;
+ rule->tag = (victim ? victim->tag
+ : table_id == 0 ? 0
+ : rule_calculate_tag(&rule->up.cr.flow, &rule->up.cr.wc,
+ ofproto->tables[table_id].basis));
+
+ complete_operation(rule);
+ return 0;
+}
+
+static void
+rule_destruct(struct rule *rule_)
+{
+ struct rule_dpif *rule = rule_dpif_cast(rule_);
+ struct facet *facet, *next_facet;
+
+ LIST_FOR_EACH_SAFE (facet, next_facet, list_node, &rule->facets) {
+ facet_revalidate(facet);
+ }
+
+ complete_operation(rule);
+}
+
+static void
+rule_get_stats(struct rule *rule_, uint64_t *packets, uint64_t *bytes)
+{
+ struct rule_dpif *rule = rule_dpif_cast(rule_);
+ struct facet *facet;
+
+ /* Start from historical data for 'rule' itself that are no longer tracked
+ * in facets. This counts, for example, facets that have expired. */
+ *packets = rule->packet_count;
+ *bytes = rule->byte_count;
+
+ /* Add any statistics that are tracked by facets. This includes
+ * statistical data recently updated by ofproto_update_stats() as well as
+ * stats for packets that were executed "by hand" via dpif_execute(). */
+ LIST_FOR_EACH (facet, list_node, &rule->facets) {
+ *packets += facet->packet_count;
+ *bytes += facet->byte_count;
+ }
+}
+
+static enum ofperr
+rule_execute(struct rule *rule_, const struct flow *flow,
+ struct ofpbuf *packet)
+{
+ struct rule_dpif *rule = rule_dpif_cast(rule_);
+ struct ofproto_dpif *ofproto = ofproto_dpif_cast(rule->up.ofproto);
+ struct action_xlate_ctx ctx;
+ struct ofpbuf *odp_actions;
+ size_t size;
+
+ action_xlate_ctx_init(&ctx, ofproto, flow, flow->vlan_tci,
+ rule, packet_get_tcp_flags(packet, flow), packet);