ofproto: Fix is_flow_deletion_pending() false positive.
[sliver-openvswitch.git] / ofproto / ofproto.c
index 6195b75..eb1f3be 100644 (file)
@@ -1975,14 +1975,13 @@ ofproto_flow_mod(struct ofproto *ofproto, struct ofputil_flow_mod *fm)
     if (fm->command == OFPFC_MODIFY_STRICT && fm->table_id != OFPTT_ALL
         && !(fm->flags & OFPUTIL_FF_RESET_COUNTS)) {
         struct oftable *table = &ofproto->tables[fm->table_id];
-        struct cls_rule match_rule;
         struct rule *rule;
         bool done = false;
 
-        cls_rule_init(&match_rule, &fm->match, fm->priority);
         fat_rwlock_rdlock(&table->cls.rwlock);
-        rule = rule_from_cls_rule(classifier_find_rule_exactly(&table->cls,
-                                                               &match_rule));
+        rule = rule_from_cls_rule(classifier_find_match_exactly(&table->cls,
+                                                                &fm->match,
+                                                                fm->priority));
         if (rule) {
             /* Reading many of the rule fields and writing on 'modified'
              * requires the rule->mutex.  Also, rule->actions may change
@@ -3954,7 +3953,8 @@ is_flow_deletion_pending(const struct ofproto *ofproto,
         HMAP_FOR_EACH_WITH_HASH (op, hmap_node,
                                  cls_rule_hash(cls_rule, table_id),
                                  &ofproto->deletions) {
-            if (cls_rule_equal(cls_rule, &op->rule->cr)) {
+            if (op->rule->table_id == table_id
+                && cls_rule_equal(cls_rule, &op->rule->cr)) {
                 return true;
             }
         }
@@ -6992,25 +6992,30 @@ ofproto_unixctl_init(void)
 void
 ofproto_get_vlan_usage(struct ofproto *ofproto, unsigned long int *vlan_bitmap)
 {
+    struct match match;
+    struct cls_rule target;
     const struct oftable *oftable;
 
+    match_init_catchall(&match);
+    match_set_vlan_vid_masked(&match, htons(VLAN_CFI), htons(VLAN_CFI));
+    cls_rule_init(&target, &match, 0);
+
     free(ofproto->vlan_bitmap);
     ofproto->vlan_bitmap = bitmap_allocate(4096);
     ofproto->vlans_changed = false;
 
     OFPROTO_FOR_EACH_TABLE (oftable, ofproto) {
-        const struct cls_subtable *table;
+        struct cls_cursor cursor;
+        struct rule *rule;
 
         fat_rwlock_rdlock(&oftable->cls.rwlock);
-        HMAP_FOR_EACH (table, hmap_node, &oftable->cls.subtables) {
-            if (minimask_get_vid_mask(&table->mask) == VLAN_VID_MASK) {
-                const struct cls_rule *rule;
-
-                HMAP_FOR_EACH (rule, hmap_node, &table->rules) {
-                    uint16_t vid = miniflow_get_vid(&rule->match.flow);
-                    bitmap_set1(vlan_bitmap, vid);
-                    bitmap_set1(ofproto->vlan_bitmap, vid);
-                }
+        cls_cursor_init(&cursor, &oftable->cls, &target);
+        CLS_CURSOR_FOR_EACH (rule, cr, &cursor) {
+            if (minimask_get_vid_mask(&rule->cr.match.mask) == VLAN_VID_MASK) {
+                uint16_t vid = miniflow_get_vid(&rule->cr.match.flow);
+
+                bitmap_set1(vlan_bitmap, vid);
+                bitmap_set1(ofproto->vlan_bitmap, vid);
             }
         }
         fat_rwlock_unlock(&oftable->cls.rwlock);