+ * With one exception, when an asynchronous operation completes with an
+ * error, ofoperation_complete() backs out the already applied changes:
+ *
+ * - If adding or replacing a rule in the flow table fails, ofproto
+ * removes the new rule or restores the original rule.
+ *
+ * - If modifying a rule's actions fails, ofproto restores the original
+ * actions.
+ *
+ * - Removing a rule is not allowed to fail. It must always succeed.
+ *
+ * The ofproto base code serializes operations: if any operation is in
+ * progress on a given rule, ofproto postpones initiating any new operation
+ * on that rule until the pending operation completes. Therefore, every
+ * operation must eventually complete through a call to
+ * ofoperation_complete() to avoid delaying new operations indefinitely
+ * (including any OpenFlow request that affects the rule in question, even
+ * just to query its statistics).
+ *
+ *
+ * Construction
+ * ============
+ *
+ * When ->rule_construct() is called, the caller has already inserted
+ * 'rule' into 'rule->ofproto''s flow table numbered 'rule->table_id'.
+ * There are two cases:
+ *
+ * - 'rule' is a new rule in its flow table. In this case,
+ * ofoperation_get_victim(rule) returns NULL.
+ *
+ * - 'rule' is replacing an existing rule in its flow table that had the
+ * same matching criteria and priority. In this case,
+ * ofoperation_get_victim(rule) returns the rule being replaced.
+ *
+ * ->rule_construct() should set the following in motion:
+ *
+ * - Validate that the matching rule in 'rule->cr' is supported by the
+ * datapath. For example, if the rule's table does not support
+ * registers, then it is an error if 'rule->cr' does not wildcard all