Use new method to describe table entries in OpenFlow wire protocol.
[sliver-openvswitch.git] / datapath / hwtable_dummy / hwtable_dummy.c
index b6c5832..20f72a2 100644 (file)
 #define DUMMY_MAX_FLOW   8192
 
 
-/* xxx Explain need for this separate list because of RCU */
-static spinlock_t pending_free_lock;
-static struct list_head pending_free_list;
-
 /* sw_flow private data for dummy table entries.  */
 struct sw_flow_dummy {
        struct list_head node;
@@ -63,50 +59,21 @@ struct sw_flow_dummy {
 struct sw_table_dummy {
        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;
 };
 
 
-static void table_dummy_sfw_destroy(struct sw_flow_dummy *sfw)
-{
-       /* xxx Remove the entry from hardware.  If you need to do any other
-        * xxx clean-up associated with the entry, do it here.
-        */
-
-       kfree(sfw);
-}
-
-static void table_dummy_rcu_callback(struct rcu_head *rcu)
-{
-       struct sw_flow *flow = container_of(rcu, struct sw_flow, rcu);
-
-       spin_lock(&pending_free_lock);
-       if (flow->private) {
-               struct sw_flow_dummy *sfw = flow->private;
-               list_add(&sfw->node, &pending_free_list);
-               flow->private = NULL;
-       }
-       spin_unlock(&pending_free_lock);
-       flow_free(flow);
-}
-
-static void table_dummy_flow_deferred_free(struct sw_flow *flow)
-{
-       call_rcu(&flow->rcu, table_dummy_rcu_callback);
-}
-
 static struct sw_flow *table_dummy_lookup(struct sw_table *swt,
                                          const struct sw_flow_key *key)
 {
        struct sw_table_dummy *td = (struct sw_table_dummy *) swt;
        struct sw_flow *flow;
        list_for_each_entry (flow, &td->flows, node) {
-               if (flow_matches(&flow->key, key)) {
+               if (flow_matches_1wild(key, &flow->key)) {
                        return flow; 
                }
        }
@@ -123,7 +90,8 @@ static int table_dummy_insert(struct sw_table *swt, struct sw_flow *flow)
        /* xxx Do whatever needs to be done to insert an entry in hardware. 
         * xxx If the entry can't be inserted, return 0.  This stub code
         * xxx doesn't do anything yet, so we're going to return 0...you
-        * xxx shouldn't.
+        * xxx shouldn't (and you should update n_flows in struct
+        * xxx sw_table_dummy, too).
         */
        kfree(flow->private);
        return 0;
@@ -132,13 +100,12 @@ static int table_dummy_insert(struct sw_table *swt, struct sw_flow *flow)
 
 static int do_delete(struct sw_table *swt, struct sw_flow *flow)
 {
-       if (flow_del(flow)) {
-               list_del_rcu(&flow->node);
-               list_del_rcu(&flow->iter_node);
-               table_dummy_flow_deferred_free(flow);
-               return 1;
-       }
-       return 0;
+       /* xxx Remove the entry from hardware.  If you need to do any other
+        * xxx clean-up associated with the entry, do it here.
+        */
+       list_del_rcu(&flow->node);
+       list_del_rcu(&flow->iter_node);
+       return 1;
 }
 
 static int table_dummy_delete(struct sw_table *swt,
@@ -148,13 +115,12 @@ static int table_dummy_delete(struct sw_table *swt,
        struct sw_flow *flow;
        unsigned int count = 0;
 
-       list_for_each_entry_rcu (flow, &td->flows, node) {
+       list_for_each_entry (flow, &td->flows, node) {
                if (flow_del_matches(&flow->key, key, strict)
                    && (!strict || (flow->priority == priority)))
                        count += do_delete(swt, flow);
        }
-       if (count)
-               atomic_sub(count, &td->n_flows);
+       td->n_flows -= count;
        return count;
 }
 
@@ -163,46 +129,36 @@ static int table_dummy_timeout(struct datapath *dp, struct sw_table *swt)
 {
        struct sw_table_dummy *td = (struct sw_table_dummy *) swt;
        struct sw_flow *flow;
-       struct sw_flow_dummy *sfw, *n;
        int del_count = 0;
        uint64_t packet_count = 0;
-       int i = 0;
+       uint64_t byte_count = 0;
+       int reason;
 
-       list_for_each_entry_rcu (flow, &td->flows, node) {
-               /* xxx Retrieve the packet count associated with this entry
-                * xxx and store it in "packet_count".
+       mutex_lock(&dp_mutex);
+       list_for_each_entry (flow, &td->flows, node) {
+               /* xxx Retrieve the packet and byte counts associated with this
+                * entry xxx and store them in "packet_count" and "byte_count".
                 */
 
-               if ((packet_count > flow->packet_count)
-                    && (flow->max_idle != OFP_FLOW_PERMANENT)) {
+               if (packet_count != flow->packet_count) {
                        flow->packet_count = packet_count;
-                       flow->timeout = jiffies + HZ * flow->max_idle;
+                       flow->byte_count = byte_count;
+                       flow->used = jiffies;
                }
 
-               if (flow_timeout(flow)) {
+               reason = flow_timeout(flow);
+               if (reason >= 0) {
                        if (dp->flags & OFPC_SEND_FLOW_EXP) {
                                /* xxx Get byte count */
                                flow->byte_count = 0;
-                               dp_send_flow_expired(dp, flow);
+                               dp_send_flow_expired(dp, flow, reason);
                        }
                        del_count += do_delete(swt, flow);
                }
-               if ((i % 50) == 0) {
-                       msleep_interruptible(1);
-               }
-               i++;
        }
+       mutex_unlock(&dp_mutex);
 
-       /* Remove any entries queued for removal */
-       spin_lock_bh(&pending_free_lock);
-       list_for_each_entry_safe (sfw, n, &pending_free_list, node) {
-               list_del(&sfw->node);
-               table_dummy_sfw_destroy(sfw);
-       }
-       spin_unlock_bh(&pending_free_lock);
-
-       if (del_count)
-               atomic_sub(del_count, &td->n_flows);
+       td->n_flows -= del_count;
        return del_count;
 }
 
@@ -239,8 +195,9 @@ static int table_dummy_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)) {
                        int error = callback(flow, private);
                        if (error) {
                                position->private[0] = ~flow->serial;
@@ -256,8 +213,10 @@ static void table_dummy_stats(struct sw_table *swt,
 {
        struct sw_table_dummy *td = (struct sw_table_dummy *) swt;
        stats->name = "dummy";
-       stats->n_flows = atomic_read(&td->n_flows);
+       stats->wildcards = OFPFW_ALL;      /* xxx Set this appropriately */
+       stats->n_flows   = td->n_flows;
        stats->max_flows = td->max_flows;
+       stats->n_matched = swt->n_matched;
 }
 
 
@@ -280,15 +239,11 @@ static struct sw_table *table_dummy_create(void)
        swt->stats = table_dummy_stats;
 
        td->max_flows = DUMMY_MAX_FLOW;
-       atomic_set(&td->n_flows, 0);
+       td->n_flows = 0;
        INIT_LIST_HEAD(&td->flows);
        INIT_LIST_HEAD(&td->iter_flows);
-       spin_lock_init(&td->lock);
        td->next_serial = 0;
 
-       INIT_LIST_HEAD(&pending_free_list);
-       spin_lock_init(&pending_free_lock);
-
        return swt;
 }