return subrule;
}
+/* Remove 'rule' from 'ofproto' and free up the associated memory:
+ *
+ * - If 'rule' was installed in the datapath, uninstalls it and updates
+ * 'rule''s statistics (or its super-rule's statistics, if it is a
+ * subrule), via rule_uninstall().
+ *
+ * - Removes 'rule' from the classifier.
+ *
+ * - If 'rule' is a super-rule that has subrules, revalidates (and possibly
+ * uninstalls and destroys) its subrules, via rule_destroy().
+ */
static void
rule_remove(struct ofproto *ofproto, struct rule *rule)
{
}
}
+/* 'rule' must be an exact-match rule in 'p'.
+ *
+ * If 'rule' is installed in the datapath, uninstalls it and updates's
+ * statistics. If 'rule' is a subrule, the statistics that are updated are
+ * actually its super-rule's statistics; otherwise 'rule''s own statistics are
+ * updated.
+ *
+ * If 'rule' is not installed, this function has no effect. */
static void
rule_uninstall(struct ofproto *p, struct rule *rule)
{
expired.used = rule->used;
netflow_expire(ofproto->netflow, &rule->nf_flow, &expired);
-
- /* Schedule us to send the accumulated records once we have
- * collected all of them. */
- poll_immediate_wake();
}
}
now = time_msec();
if (now < expire) {
/* 'rule' has not expired according to OpenFlow rules. */
- if (rule->installed && now >= rule->used + 5000) {
- /* This rule is idle, so uninstall it from the datapath. */
- if (rule->super) {
- rule_remove(ofproto, rule);
+ if (!rule->cr.wc.wildcards) {
+ if (now >= rule->used + 5000) {
+ /* This rule is idle, so drop it to free up resources. */
+ if (rule->super) {
+ /* It's not part of the OpenFlow flow table, so we can
+ * delete it entirely and fold its statistics into its
+ * super-rule. */
+ rule_remove(ofproto, rule);
+ } else {
+ /* It is part of the OpenFlow flow table, so we have to
+ * keep the rule but we can at least uninstall it from the
+ * datapath. */
+ rule_uninstall(ofproto, rule);
+ }
} else {
- rule_uninstall(ofproto, rule);
+ /* Send NetFlow active timeout if appropriate. */
+ rule_active_timeout(cbdata->ofproto, rule);
}
- } else if (!rule->cr.wc.wildcards) {
- /* Send NetFlow active timeout if appropriate. */
- rule_active_timeout(cbdata->ofproto, rule);
}
} else {
/* 'rule' has expired according to OpenFlow rules. */
struct ofconn *prev;
struct ofpbuf *buf = NULL;
+ if (!rule->send_flow_removed) {
+ return;
+ }
+
/* We limit the maximum number of queued flow expirations it by accounting
* them under the counter for replies. That works because preventing
* OpenFlow requests from being processed also prevents new flows from
prev = NULL;
LIST_FOR_EACH (ofconn, struct ofconn, node, &p->all_conns) {
- if (rule->send_flow_removed && rconn_is_connected(ofconn->rconn)
+ if (rconn_is_connected(ofconn->rconn)
&& ofconn_receives_async_msgs(ofconn)) {
if (prev) {
queue_tx(ofpbuf_clone(buf), prev, prev->reply_counter);