ofproto-dpif-xlate: Distinguish "freezing" from "recirculation".
[cascardo/ovs.git] / ofproto / ofproto-dpif-mirror.c
index 9734718..6f8079a 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
+/* Copyright (c) 2009, 2010, 2011, 2012, 2013, 2015 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -22,7 +22,7 @@
 #include "hmapx.h"
 #include "ofproto.h"
 #include "vlan-bitmap.h"
-#include "vlog.h"
+#include "openvswitch/vlog.h"
 
 VLOG_DEFINE_THIS_MODULE(ofproto_dpif_mirror);
 
@@ -36,7 +36,7 @@ struct mbridge {
     bool need_revalidate;
     bool has_mirrors;
 
-    int ref_cnt;
+    struct ovs_refcount ref_cnt;
 };
 
 struct mbundle {
@@ -75,7 +75,6 @@ static void mbundle_lookup_multiple(const struct mbridge *, struct ofbundle **,
                                   size_t n_bundles, struct hmapx *mbundles);
 static int mirror_scan(struct mbridge *);
 static void mirror_update_dups(struct mbridge *);
-static int mirror_mask_ffs(mirror_mask_t);
 
 struct mbridge *
 mbridge_create(void)
@@ -83,7 +82,7 @@ mbridge_create(void)
     struct mbridge *mbridge;
 
     mbridge = xzalloc(sizeof *mbridge);
-    mbridge->ref_cnt = 1;
+    ovs_refcount_init(&mbridge->ref_cnt);
 
     hmap_init(&mbridge->mbundles);
     return mbridge;
@@ -94,8 +93,7 @@ mbridge_ref(const struct mbridge *mbridge_)
 {
     struct mbridge *mbridge = CONST_CAST(struct mbridge *, mbridge_);
     if (mbridge) {
-        ovs_assert(mbridge->ref_cnt > 0);
-        mbridge->ref_cnt++;
+        ovs_refcount_ref(&mbridge->ref_cnt);
     }
     return mbridge;
 }
@@ -110,22 +108,20 @@ mbridge_unref(struct mbridge *mbridge)
         return;
     }
 
-    ovs_assert(mbridge->ref_cnt > 0);
-    if (--mbridge->ref_cnt) {
-        return;
-    }
+    if (ovs_refcount_unref(&mbridge->ref_cnt) == 1) {
+        for (i = 0; i < MAX_MIRRORS; i++) {
+            if (mbridge->mirrors[i]) {
+                mirror_destroy(mbridge, mbridge->mirrors[i]->aux);
+            }
+        }
 
-    for (i = 0; i < MAX_MIRRORS; i++) {
-        if (mbridge->mirrors[i]) {
-            mirror_destroy(mbridge, mbridge->mirrors[i]->aux);
+        HMAP_FOR_EACH_SAFE (mbundle, next, hmap_node, &mbridge->mbundles) {
+            mbridge_unregister_bundle(mbridge, mbundle->ofbundle);
         }
-    }
 
-    HMAP_FOR_EACH_SAFE (mbundle, next, hmap_node, &mbridge->mbundles) {
-        mbridge_unregister_bundle(mbridge, mbundle->ofbundle);
+        hmap_destroy(&mbridge->mbundles);
+        free(mbridge);
     }
-
-    free(mbridge);
 }
 
 bool
@@ -135,11 +131,13 @@ mbridge_has_mirrors(struct mbridge *mbridge)
 }
 
 /* Returns true if configurations changes in 'mbridge''s mirrors require
- * revalidation. */
+ * revalidation, and resets the revalidation flag to false. */
 bool
 mbridge_need_revalidate(struct mbridge *mbridge)
 {
-    return mbridge->need_revalidate;
+    bool need_revalidate = mbridge->need_revalidate;
+    mbridge->need_revalidate = false;
+    return need_revalidate;
 }
 
 void
@@ -362,7 +360,7 @@ mirror_update_stats(struct mbridge *mbridge, mirror_mask_t mirrors,
     for (; mirrors; mirrors = zero_rightmost_1bit(mirrors)) {
         struct mirror *m;
 
-        m = mbridge->mirrors[mirror_mask_ffs(mirrors) - 1];
+        m = mbridge->mirrors[raw_ctz(mirrors)];
 
         if (!m) {
             /* In normal circumstances 'm' will not be NULL.  However,
@@ -379,11 +377,17 @@ mirror_update_stats(struct mbridge *mbridge, mirror_mask_t mirrors,
     }
 }
 
-/* Retrieves the mirror in 'mbridge' represented by the first bet set of
- * 'mirrors'.  Returns true if such a mirror exists, false otherwise.
- * The caller takes ownership of, and is expected to deallocate, 'vlans' */
+/* Retrieves the mirror numbered 'index' in 'mbridge'.  Returns true if such a
+ * mirror exists, false otherwise.
+ *
+ * If successful, '*vlans' receives the mirror's VLAN membership information,
+ * either a null pointer if the mirror includes all VLANs or a 4096-bit bitmap
+ * in which a 1-bit indicates that the mirror includes a particular VLAN,
+ * '*dup_mirrors' receives a bitmap of mirrors whose output duplicates mirror
+ * 'index', '*out' receives the output ofbundle (if any), and '*out_vlan'
+ * receives the output VLAN (if any). */
 bool
-mirror_get(struct mbridge *mbridge, int index, unsigned long **vlans,
+mirror_get(struct mbridge *mbridge, int index, const unsigned long **vlans,
            mirror_mask_t *dup_mirrors, struct ofbundle **out, int *out_vlan)
 {
     struct mirror *mirror;
@@ -397,7 +401,7 @@ mirror_get(struct mbridge *mbridge, int index, unsigned long **vlans,
         return false;
     }
 
-    *vlans = vlan_bitmap_clone(mirror->vlans);
+    *vlans = mirror->vlans;
     *dup_mirrors = mirror->dup_mirrors;
     *out = mirror->out ? mirror->out->ofbundle : NULL;
     *out_vlan = mirror->out_vlan;