#include <linux/rcupdate.h>
#include <linux/slab.h>
-#include <linux/list.h>
+#include <linux/rculist.h>
struct sw_table_linear {
struct sw_table swt;
struct sw_table_linear *tl = (struct sw_table_linear *) swt;
struct sw_flow *flow;
list_for_each_entry_rcu (flow, &tl->flows, node) {
- if (flow_matches(&flow->key, key))
+ if (flow_matches_1wild(key, &flow->key))
return flow;
}
return NULL;
list_for_each_entry (f, &tl->flows, node) {
if (f->priority == flow->priority
&& f->key.wildcards == flow->key.wildcards
- && flow_matches(&f->key, &flow->key)
- && flow_del(f)) {
+ && flow_matches_2wild(&f->key, &flow->key)) {
+ /* Keep stats from the original flow */
+ flow->init_time = f->init_time;
+ flow->packet_count = f->packet_count;
+ flow->byte_count = f->byte_count;
+
flow->serial = f->serial;
list_replace_rcu(&f->node, &flow->node);
list_replace_rcu(&f->iter_node, &flow->iter_node);
return 1;
}
-static int do_delete(struct sw_table *swt, struct sw_flow *flow)
+static int table_linear_modify(struct sw_table *swt,
+ const struct sw_flow_key *key,
+ const struct ofp_action *actions, int n_actions)
{
- if (flow_del(flow)) {
- list_del_rcu(&flow->node);
- list_del_rcu(&flow->iter_node);
- flow_deferred_free(flow);
- return 1;
+ struct sw_table_linear *tl = (struct sw_table_linear *) swt;
+ struct sw_flow *flow;
+ unsigned int count = 0;
+
+ list_for_each_entry (flow, &tl->flows, node) {
+ if (flow_matches_1wild(&flow->key, key)) {
+ flow_replace_acts(flow, actions, n_actions);
+ count++;
+ }
}
- return 0;
+ return count;
+}
+
+static int do_delete(struct sw_table *swt, struct sw_flow *flow)
+{
+ list_del_rcu(&flow->node);
+ list_del_rcu(&flow->iter_node);
+ flow_deferred_free(flow);
+ return 1;
}
static int table_linear_delete(struct sw_table *swt,
mutex_lock(&dp_mutex);
list_for_each_entry (flow, &tl->flows, node) {
- if (flow_timeout(flow)) {
+ int reason = flow_timeout(flow);
+ if (reason >= 0) {
count += do_delete(swt, flow);
- if (dp->flags & OFPC_SEND_FLOW_EXP)
- dp_send_flow_expired(dp, flow);
+ dp_send_flow_expired(dp, flow, reason);
}
}
tl->n_flows -= count;
start = position->private[0];
list_for_each_entry (flow, &tl->iter_flows, iter_node) {
- if (flow->serial >= start && flow_matches(key, &flow->key)) {
+ if (flow->serial >= start
+ && flow_matches_2wild(key, &flow->key)) {
int error = callback(flow, private);
if (error) {
position->private[0] = flow->serial;
{
struct sw_table_linear *tl = (struct sw_table_linear *) swt;
stats->name = "linear";
- stats->n_flows = tl->n_flows;
+ stats->wildcards = OFPFW_ALL;
+ stats->n_flows = tl->n_flows;
stats->max_flows = tl->max_flows;
+ stats->n_matched = swt->n_matched;
}
swt = &tl->swt;
swt->lookup = table_linear_lookup;
swt->insert = table_linear_insert;
+ swt->modify = table_linear_modify;
swt->delete = table_linear_delete;
swt->timeout = table_linear_timeout;
swt->destroy = table_linear_destroy;