return flow;
}
-static void dp_table_swap(struct datapath *dp, struct dp_table *new_table,
- int free_flows)
-{
- struct dp_table *old_table = rcu_dereference(dp->table);
- rcu_assign_pointer(dp->table, new_table);
- synchronize_rcu();
- dp_table_destroy(old_table, free_flows);
-}
-
int dp_table_foreach(struct dp_table *table,
int (*callback)(struct sw_flow *flow, void *aux),
void *aux)
return 0;
}
+static void dp_free_table_rcu(struct rcu_head *rcu)
+{
+ struct dp_table *table = container_of(rcu, struct dp_table, rcu);
+ dp_table_destroy(table, 0);
+}
+
int dp_table_expand(struct datapath *dp)
{
struct dp_table *old_table = rcu_dereference(dp->table);
if (!new_table)
return -ENOMEM;
dp_table_foreach(old_table, insert_flow, new_table);
- dp_table_swap(dp, new_table, 0);
+ rcu_assign_pointer(dp->table, new_table);
+ call_rcu(&old_table->rcu, dp_free_table_rcu);
return 0;
}
+static void dp_free_table_and_flows_rcu(struct rcu_head *rcu)
+{
+ struct dp_table *table = container_of(rcu, struct dp_table, rcu);
+ dp_table_destroy(table, 1);
+}
+
int dp_table_flush(struct datapath *dp)
{
+ struct dp_table *old_table = rcu_dereference(dp->table);
struct dp_table *new_table = dp_table_create(DP_L1_SIZE);
if (!new_table)
return -ENOMEM;
- dp_table_swap(dp, new_table, 1);
+ rcu_assign_pointer(dp->table, new_table);
+ call_rcu(&old_table->rcu, dp_free_table_and_flows_rcu);
return 0;
}