dpif-netdev: init atomic flag dp->destroyed
[sliver-openvswitch.git] / lib / dpif-netdev.c
index 9ba93dd..3bbfd2a 100644 (file)
@@ -448,7 +448,7 @@ create_dp_netdev(const char *name, const struct dpif_class *class,
     *CONST_CAST(const struct dpif_class **, &dp->class) = class;
     *CONST_CAST(const char **, &dp->name) = xstrdup(name);
     ovs_refcount_init(&dp->ref_cnt);
-    atomic_flag_init(&dp->destroyed);
+    atomic_flag_clear(&dp->destroyed);
 
     ovs_mutex_init(&dp->flow_mutex);
     classifier_init(&dp->cls, NULL);
@@ -558,8 +558,6 @@ dp_netdev_free(struct dp_netdev *dp)
     ovs_mutex_destroy(&dp->flow_mutex);
     seq_destroy(dp->port_seq);
     hmap_destroy(&dp->ports);
-    atomic_flag_destroy(&dp->destroyed);
-    ovs_refcount_destroy(&dp->ref_cnt);
     latch_destroy(&dp->exit_latch);
     free(CONST_CAST(char *, dp->name));
     free(dp);
@@ -871,7 +869,6 @@ dp_netdev_flow_unref(struct dp_netdev_flow *flow)
         cls_rule_destroy(CONST_CAST(struct cls_rule *, &flow->cr));
         ovs_mutex_lock(&flow->mutex);
         dp_netdev_actions_unref(flow->actions);
-        ovs_refcount_destroy(&flow->ref_cnt);
         ovs_mutex_unlock(&flow->mutex);
         ovs_mutex_destroy(&flow->mutex);
         free(flow);
@@ -1295,6 +1292,7 @@ dpif_netdev_flow_del(struct dpif *dpif, const struct dpif_flow_del *del)
             ovs_mutex_unlock(&netdev_flow->mutex);
         }
         dp_netdev_remove_flow(dp, netdev_flow);
+        dp_netdev_flow_unref(netdev_flow);
     } else {
         error = ENOENT;
     }
@@ -1305,47 +1303,82 @@ dpif_netdev_flow_del(struct dpif *dpif, const struct dpif_flow_del *del)
 }
 
 struct dp_netdev_flow_state {
-    uint32_t bucket;
-    uint32_t offset;
     struct dp_netdev_actions *actions;
     struct odputil_keybuf keybuf;
     struct odputil_keybuf maskbuf;
     struct dpif_flow_stats stats;
 };
 
-static int
-dpif_netdev_flow_dump_start(const struct dpif *dpif OVS_UNUSED, void **statep)
+struct dp_netdev_flow_iter {
+    uint32_t bucket;
+    uint32_t offset;
+    int status;
+    struct ovs_mutex mutex;
+};
+
+static void
+dpif_netdev_flow_dump_state_init(void **statep)
 {
     struct dp_netdev_flow_state *state;
 
     *statep = state = xmalloc(sizeof *state);
-    state->bucket = 0;
-    state->offset = 0;
     state->actions = NULL;
+}
+
+static void
+dpif_netdev_flow_dump_state_uninit(void *state_)
+{
+    struct dp_netdev_flow_state *state = state_;
+
+    dp_netdev_actions_unref(state->actions);
+    free(state);
+}
+
+static int
+dpif_netdev_flow_dump_start(const struct dpif *dpif OVS_UNUSED, void **iterp)
+{
+    struct dp_netdev_flow_iter *iter;
+
+    *iterp = iter = xmalloc(sizeof *iter);
+    iter->bucket = 0;
+    iter->offset = 0;
+    iter->status = 0;
+    ovs_mutex_init(&iter->mutex);
     return 0;
 }
 
 static int
-dpif_netdev_flow_dump_next(const struct dpif *dpif, void *state_,
+dpif_netdev_flow_dump_next(const struct dpif *dpif, void *iter_, void *state_,
                            const struct nlattr **key, size_t *key_len,
                            const struct nlattr **mask, size_t *mask_len,
                            const struct nlattr **actions, size_t *actions_len,
                            const struct dpif_flow_stats **stats)
 {
+    struct dp_netdev_flow_iter *iter = iter_;
     struct dp_netdev_flow_state *state = state_;
     struct dp_netdev *dp = get_dp_netdev(dpif);
     struct dp_netdev_flow *netdev_flow;
-    struct hmap_node *node;
+    int error;
 
-    fat_rwlock_rdlock(&dp->cls.rwlock);
-    node = hmap_at_position(&dp->flow_table, &state->bucket, &state->offset);
-    if (node) {
-        netdev_flow = CONTAINER_OF(node, struct dp_netdev_flow, node);
-        dp_netdev_flow_ref(netdev_flow);
+    ovs_mutex_lock(&iter->mutex);
+    error = iter->status;
+    if (!error) {
+        struct hmap_node *node;
+
+        fat_rwlock_rdlock(&dp->cls.rwlock);
+        node = hmap_at_position(&dp->flow_table, &iter->bucket, &iter->offset);
+        if (node) {
+            netdev_flow = CONTAINER_OF(node, struct dp_netdev_flow, node);
+            dp_netdev_flow_ref(netdev_flow);
+        }
+        fat_rwlock_unlock(&dp->cls.rwlock);
+        if (!node) {
+            iter->status = error = EOF;
+        }
     }
-    fat_rwlock_unlock(&dp->cls.rwlock);
-    if (!node) {
-        return EOF;
+    ovs_mutex_unlock(&iter->mutex);
+    if (error) {
+        return error;
     }
 
     if (key) {
@@ -1396,12 +1429,12 @@ dpif_netdev_flow_dump_next(const struct dpif *dpif, void *state_,
 }
 
 static int
-dpif_netdev_flow_dump_done(const struct dpif *dpif OVS_UNUSED, void *state_)
+dpif_netdev_flow_dump_done(const struct dpif *dpif OVS_UNUSED, void *iter_)
 {
-    struct dp_netdev_flow_state *state = state_;
+    struct dp_netdev_flow_iter *iter = iter_;
 
-    dp_netdev_actions_unref(state->actions);
-    free(state);
+    ovs_mutex_destroy(&iter->mutex);
+    free(iter);
     return 0;
 }
 
@@ -1418,8 +1451,7 @@ dpif_netdev_execute(struct dpif *dpif, struct dpif_execute *execute)
     }
 
     /* Extract flow key. */
-    flow_extract(execute->packet, md->skb_priority, md->pkt_mark, &md->tunnel,
-                 (union flow_in_port *)&md->in_port, &key);
+    flow_extract(execute->packet, md, &key);
 
     ovs_rwlock_rdlock(&dp->port_rwlock);
     dp_netdev_execute_actions(dp, &key, execute->packet, md, execute->actions,
@@ -1544,7 +1576,6 @@ void
 dp_netdev_actions_unref(struct dp_netdev_actions *actions)
 {
     if (actions && ovs_refcount_unref(&actions->ref_cnt) == 1) {
-        ovs_refcount_destroy(&actions->ref_cnt);
         free(actions->actions);
         free(actions);
     }
@@ -1591,8 +1622,8 @@ dp_forwarder_main(void *f_)
                     if (!error) {
                         struct pkt_metadata md
                             = PKT_METADATA_INITIALIZER(port->port_no);
-                        dp_netdev_port_input(dp, &packet, &md);
 
+                        dp_netdev_port_input(dp, &packet, &md);
                         received_anything = true;
                     } else if (error != EAGAIN && error != EOPNOTSUPP) {
                         static struct vlog_rate_limit rl
@@ -1692,8 +1723,7 @@ dp_netdev_port_input(struct dp_netdev *dp, struct ofpbuf *packet,
     if (packet->size < ETH_HEADER_LEN) {
         return;
     }
-    flow_extract(packet, md->skb_priority, md->pkt_mark, &md->tunnel,
-                 (union flow_in_port *)&md->in_port, &key);
+    flow_extract(packet, md, &key);
     netdev_flow = dp_netdev_lookup_flow(dp, &key);
     if (netdev_flow) {
         struct dp_netdev_actions *actions;
@@ -1706,6 +1736,7 @@ dp_netdev_port_input(struct dp_netdev *dp, struct ofpbuf *packet,
         dp_netdev_execute_actions(dp, &key, packet, md,
                                   actions->actions, actions->size);
         dp_netdev_actions_unref(actions);
+        dp_netdev_flow_unref(netdev_flow);
         ovsthread_counter_inc(dp->n_hit, 1);
     } else {
         ovsthread_counter_inc(dp->n_missed, 1);
@@ -1852,9 +1883,12 @@ const struct dpif_class dpif_netdev_class = {
     dpif_netdev_flow_put,
     dpif_netdev_flow_del,
     dpif_netdev_flow_flush,
+    dpif_netdev_flow_dump_state_init,
     dpif_netdev_flow_dump_start,
     dpif_netdev_flow_dump_next,
+    NULL,
     dpif_netdev_flow_dump_done,
+    dpif_netdev_flow_dump_state_uninit,
     dpif_netdev_execute,
     NULL,                       /* operate */
     dpif_netdev_recv_set,