X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=datapath%2Ftable-linear.c;h=1d5e186d2d28e3584554dbf7e187762abeea968d;hb=2e24b5fdefd892579657135f7e3eff2fc4abce50;hp=68c3aed11ad99229597f87b85b4af22651043ad8;hpb=4f8e1eb53926244233eb4521f46354d1fc206359;p=sliver-openvswitch.git diff --git a/datapath/table-linear.c b/datapath/table-linear.c index 68c3aed11..1d5e186d2 100644 --- a/datapath/table-linear.c +++ b/datapath/table-linear.c @@ -10,14 +10,13 @@ #include #include -#include +#include struct sw_table_linear { struct sw_table swt; - spinlock_t lock; unsigned int max_flows; - atomic_t n_flows; + unsigned int n_flows; struct list_head flows; struct list_head iter_flows; unsigned long int next_serial; @@ -29,7 +28,7 @@ static struct sw_flow *table_linear_lookup(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; @@ -38,7 +37,6 @@ static struct sw_flow *table_linear_lookup(struct sw_table *swt, static int table_linear_insert(struct sw_table *swt, struct sw_flow *flow) { struct sw_table_linear *tl = (struct sw_table_linear *) swt; - unsigned long int flags; struct sw_flow *f; @@ -46,16 +44,13 @@ static int table_linear_insert(struct sw_table *swt, struct sw_flow *flow) * always be placed behind those with equal priority. Just replace * any flows that match exactly. */ - spin_lock_irqsave(&tl->lock, flags); - list_for_each_entry_rcu (f, &tl->flows, node) { + 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)) { flow->serial = f->serial; list_replace_rcu(&f->node, &flow->node); list_replace_rcu(&f->iter_node, &flow->iter_node); - spin_unlock_irqrestore(&tl->lock, flags); flow_deferred_free(f); return 1; } @@ -65,45 +60,61 @@ static int table_linear_insert(struct sw_table *swt, struct sw_flow *flow) } /* Make sure there's room in the table. */ - if (atomic_read(&tl->n_flows) >= tl->max_flows) { - spin_unlock_irqrestore(&tl->lock, flags); + if (tl->n_flows >= tl->max_flows) { return 0; } - atomic_inc(&tl->n_flows); + tl->n_flows++; /* Insert the entry immediately in front of where we're pointing. */ flow->serial = tl->next_serial++; list_add_tail_rcu(&flow->node, &f->node); list_add_rcu(&flow->iter_node, &tl->iter_flows); - spin_unlock_irqrestore(&tl->lock, flags); 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, uint16_t priority, int strict, + const struct ofp_action_header *actions, size_t actions_len) { - 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_desc(&flow->key, key, strict) + && (!strict || (flow->priority == priority))) { + flow_replace_acts(flow, actions, actions_len); + count++; + } } - return 0; + return count; } -static int table_linear_delete(struct sw_table *swt, - const struct sw_flow_key *key, uint16_t priority, int strict) +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); + return 1; +} + +static int table_linear_delete(struct datapath *dp, struct sw_table *swt, + const struct sw_flow_key *key, uint16_t out_port, + uint16_t priority, int strict) { struct sw_table_linear *tl = (struct sw_table_linear *) swt; struct sw_flow *flow; unsigned int count = 0; - list_for_each_entry_rcu (flow, &tl->flows, node) { - if (flow_del_matches(&flow->key, key, strict) + list_for_each_entry (flow, &tl->flows, node) { + if (flow_matches_desc(&flow->key, key, strict) + && flow_has_out_port(flow, out_port) && (!strict || (flow->priority == priority))) - count += do_delete(swt, flow); + count += do_delete(dp, swt, flow, NXFER_DELETE); } - if (count) - atomic_sub(count, &tl->n_flows); + tl->n_flows -= count; return count; } @@ -113,15 +124,15 @@ static int table_linear_timeout(struct datapath *dp, struct sw_table *swt) struct sw_flow *flow; int count = 0; - list_for_each_entry_rcu (flow, &tl->flows, node) { - if (flow_timeout(flow)) { - count += do_delete(swt, flow); - if (dp->flags & OFPC_SEND_FLOW_EXP) - dp_send_flow_expired(dp, flow); + mutex_lock(&dp_mutex); + list_for_each_entry (flow, &tl->flows, node) { + int reason = flow_timeout(flow); + if (reason >= 0) { + count += do_delete(dp, swt, flow, reason); } } - if (count) - atomic_sub(count, &tl->n_flows); + tl->n_flows -= count; + mutex_unlock(&dp_mutex); return count; } @@ -139,7 +150,7 @@ static void table_linear_destroy(struct sw_table *swt) } static int table_linear_iterate(struct sw_table *swt, - const struct sw_flow_key *key, + const struct sw_flow_key *key, uint16_t out_port, struct sw_table_position *position, int (*callback)(struct sw_flow *, void *), void *private) @@ -149,8 +160,10 @@ static int table_linear_iterate(struct sw_table *swt, unsigned long start; start = position->private[0]; - list_for_each_entry_rcu (flow, &tl->iter_flows, iter_node) { - if (flow->serial >= start && flow_matches(key, &flow->key)) { + list_for_each_entry (flow, &tl->iter_flows, iter_node) { + if (flow->serial >= start + && flow_matches_2wild(key, &flow->key) + && flow_has_out_port(flow, out_port)) { int error = callback(flow, private); if (error) { position->private[0] = flow->serial; @@ -166,8 +179,11 @@ static void table_linear_stats(struct sw_table *swt, { struct sw_table_linear *tl = (struct sw_table_linear *) swt; stats->name = "linear"; - stats->n_flows = atomic_read(&tl->n_flows); + stats->wildcards = OFPFW_ALL; + stats->n_flows = tl->n_flows; stats->max_flows = tl->max_flows; + stats->n_lookup = swt->n_lookup; + stats->n_matched = swt->n_matched; } @@ -183,6 +199,7 @@ struct sw_table *table_linear_create(unsigned int max_flows) 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; @@ -190,10 +207,9 @@ struct sw_table *table_linear_create(unsigned int max_flows) swt->stats = table_linear_stats; tl->max_flows = max_flows; - atomic_set(&tl->n_flows, 0); + tl->n_flows = 0; INIT_LIST_HEAD(&tl->flows); INIT_LIST_HEAD(&tl->iter_flows); - spin_lock_init(&tl->lock); tl->next_serial = 0; return swt;