}
/* Caller must update n_flows. */
-static int do_delete(struct sw_flow **bucket, struct sw_flow *flow)
+static int do_delete(struct datapath *dp, struct sw_flow **bucket,
+ struct sw_flow *flow, enum nx_flow_end_reason reason)
{
+ dp_send_flow_end(dp, flow, reason);
rcu_assign_pointer(*bucket, NULL);
flow_deferred_free(flow);
return 1;
struct sw_flow **bucket = find_bucket(swt, key);
struct sw_flow *flow = *bucket;
if (flow && flow_keys_equal(&flow->key, key)
- && flow_has_out_port(flow, out_port))
- count = do_delete(bucket, flow);
- dp_send_flow_end(dp, flow, NXFER_DELETE);
+ && flow_has_out_port(flow, out_port))
+ count = do_delete(dp, bucket, flow, NXFER_DELETE);
} else {
unsigned int i;
struct sw_flow *flow = *bucket;
if (flow && flow_matches_desc(&flow->key, key, strict)
&& flow_has_out_port(flow, out_port))
- count += do_delete(bucket, flow);
- dp_send_flow_end(dp, flow, NXFER_DELETE);
+ count = do_delete(dp, bucket, flow, NXFER_DELETE);
}
}
th->n_flows -= count;
if (flow) {
int reason = flow_timeout(flow);
if (reason >= 0) {
- count += do_delete(bucket, flow);
- dp_send_flow_end(dp, flow, reason);
+ count += do_delete(dp, bucket, flow, reason);
}
}
}
return count;
}
-static int do_delete(struct sw_table *swt, struct sw_flow *flow)
+static int do_delete(struct datapath *dp, struct sw_table *swt,
+ struct sw_flow *flow, enum nx_flow_end_reason reason)
{
+ dp_send_flow_end(dp, flow, reason);
list_del_rcu(&flow->node);
list_del_rcu(&flow->iter_node);
flow_deferred_free(flow);
if (flow_matches_desc(&flow->key, key, strict)
&& flow_has_out_port(flow, out_port)
&& (!strict || (flow->priority == priority)))
- count += do_delete(swt, flow);
- dp_send_flow_end(dp, flow, NXFER_DELETE);
+ count += do_delete(dp, swt, flow, NXFER_DELETE);
}
tl->n_flows -= count;
return count;
list_for_each_entry (flow, &tl->flows, node) {
int reason = flow_timeout(flow);
if (reason >= 0) {
- count += do_delete(swt, flow);
- dp_send_flow_end(dp, flow, reason);
+ count += do_delete(dp, swt, flow, reason);
}
}
tl->n_flows -= count;