}
}
+static struct rule *
+rule_create_subrule(struct ofproto *ofproto, struct rule *rule,
+ const flow_t *flow)
+{
+ struct rule *subrule = rule_create(rule, NULL, 0,
+ rule->idle_timeout, rule->hard_timeout);
+ cls_rule_from_flow(&subrule->cr, flow, 0,
+ (rule->cr.priority <= UINT16_MAX ? UINT16_MAX
+ : rule->cr.priority));
+ classifier_insert_exact(&ofproto->cls, &subrule->cr);
+
+ return subrule;
+}
+
static void
rule_remove(struct ofproto *ofproto, struct rule *rule)
{
{
struct odp_msg *msg = packet->data;
uint16_t in_port = odp_port_to_ofp_port(msg->port);
- struct rule *rule, *subrule;
+ struct rule *rule;
struct ofpbuf payload;
flow_t flow;
}
if (rule->cr.wc.wildcards) {
- struct rule *old_sr;
-
- subrule = rule_create(rule, NULL, 0,
- rule->idle_timeout, rule->hard_timeout);
- cls_rule_from_flow(&subrule->cr, &flow, 0,
- (rule->cr.priority <= UINT16_MAX ? UINT16_MAX
- : rule->cr.priority));
-
- /* Insert 'subrule' into the classifier and compose actions for it. */
- old_sr = rule_from_cls_rule(classifier_insert(&p->cls, &subrule->cr));
- if (old_sr) {
- if (!old_sr->super) {
- /* We just replaced a real rule with a subrule. We shouldn't
- * have done that. Put old_sr back and destroy the subrule. */
- cls_rule_replace(&p->cls, &subrule->cr, &old_sr->cr);
- rule_destroy(p, subrule);
- subrule = old_sr;
- } else {
- /* XXX this seems wrong: why are we accounting the old rule's
- * traffic to the new one? */
- subrule->packet_count += old_sr->packet_count;
- subrule->byte_count += old_sr->byte_count;
- rule_destroy(p, old_sr);
- rule_make_actions(p, subrule, packet);
- }
- } else {
- rule_make_actions(p, subrule, packet);
- }
-
- /* Install flow entry into datapath. */
- rule_install(p, subrule, NULL);
+ rule = rule_create_subrule(p, rule, &flow);
+ rule_make_actions(p, rule, packet);
} else {
- subrule = rule;
if (!rule->may_install) {
/* The rule is not installable, that is, we need to process every
- * packet, so do that here. */
- rule_make_actions(p, subrule, packet);
- rule_install(p, subrule, NULL);
+ * packet, so process the current packet and set its actions into
+ * 'subrule'. */
+ rule_make_actions(p, rule, packet);
} else {
- /* A flow got dropped due to a hash collision, or the packet was
- * buffered before we processed another packet from the same
- * flow. */
+ /* XXX revalidate rule if it needs it */
}
}
- /* Execute subrule on packet. */
- if (!dpif_execute(&p->dpif, msg->port, subrule->odp_actions,
- subrule->n_odp_actions, &payload)) {
- subrule->packet_count++;
- subrule->byte_count += payload.size;
+ /* Invariant: 'rule' is an exact-match rule. */
+
+ /* XXX should forcibly install the rule here, since it's possible that it
+ * got deleted externally (e.g. "dpctl dp-del-flows") and unless we
+ * re-install it here we'll end up processing every packet by hand. But
+ * the datapath doesn't provide a good interface for that. */
+ rule_install(p, rule, NULL);
+
+ /* Execute rule on packet. */
+ if (!dpif_execute(&p->dpif, msg->port, rule->odp_actions,
+ rule->n_odp_actions, &payload)) {
+ /* XXX use flow_extract_stats(). */
+ rule->packet_count++;
+ rule->byte_count += payload.size;
}
ofpbuf_delete(packet);
}