diff --git a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceIterator.java b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceIterator.java
index 0ff058d542a049cd047313109915213bad4af14d..795775c15f1f5d0852aa4fb362b4dd5ced3600ec 100644
--- a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceIterator.java
+++ b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceIterator.java
@@ -19,17 +19,15 @@ package net.floodlightcontroller.devicemanager.internal;
 
 import java.util.Arrays;
 import java.util.Iterator;
-import java.util.NoSuchElementException;
 
 import net.floodlightcontroller.devicemanager.IEntityClass;
 import net.floodlightcontroller.devicemanager.SwitchPort;
+import net.floodlightcontroller.util.FilterIterator;
 
 /**
  * An iterator for handling device queries
  */
-public class DeviceIterator implements Iterator<Device> {
-    private Iterator<Device> subIterator;
-
+public class DeviceIterator extends FilterIterator<Device> {
     private IEntityClass[] entityClasses;
     
     private Long macAddress;
@@ -37,8 +35,6 @@ public class DeviceIterator implements Iterator<Device> {
     private Integer ipv4Address; 
     private Long switchDPID;
     private Integer switchPort;
-
-    private Device next = null;
     
     /**
      * Construct a new device iterator over the key fields
@@ -57,7 +53,7 @@ public class DeviceIterator implements Iterator<Device> {
                           Integer ipv4Address, 
                           Long switchDPID,
                           Integer switchPort) {
-        super();
+        super(subIterator);
         this.entityClasses = entityClasses;
         this.subIterator = subIterator;
         this.macAddress = macAddress;
@@ -68,80 +64,57 @@ public class DeviceIterator implements Iterator<Device> {
     }
 
     @Override
-    public boolean hasNext() {
-        if (next != null) return true;
-
+    protected boolean matches(Device value) {
         boolean match;
-        while (subIterator.hasNext()) {
-            next = subIterator.next();
+        if (entityClasses != null) {
+            IEntityClass[] classes = next.getEntityClasses();
+            if (classes == null) return false;
 
-            if (entityClasses != null) {
-                IEntityClass[] classes = next.getEntityClasses();
-                if (classes == null) continue;
-
-                match = false;
-                for (IEntityClass clazz : classes) {
-                    for (IEntityClass entityClass : entityClasses) {
-                        if (clazz.equals(entityClass)) {
-                            match = true;
-                            break;
-                        }
+            match = false;
+            for (IEntityClass clazz : classes) {
+                for (IEntityClass entityClass : entityClasses) {
+                    if (clazz.equals(entityClass)) {
+                        match = true;
+                        break;
                     }
-                    if (match == true) break;
                 }
-                if (!match) continue;                
-            }
-            if (macAddress != null) {
-                if (macAddress.longValue() != next.getMACAddress())
-                    continue;
-            }
-            if (vlan != null) {
-                Short[] vlans = next.getVlanId();
-                if (Arrays.binarySearch(vlans, vlan) < 0) 
-                    continue;
+                if (match == true) break;
             }
-            if (ipv4Address != null) {
-                Integer[] ipv4Addresses = next.getIPv4Addresses();
-                if (Arrays.binarySearch(ipv4Addresses, ipv4Address) < 0) 
-                    continue;
-            }
-            if (switchDPID != null || switchPort != null) {
-                SwitchPort[] sps = next.getAttachmentPoints();
-                if (sps == null) continue;
-                
-                match = false;
-                for (SwitchPort sp : sps) {
-                    if (switchDPID != null) {
-                        if (switchDPID.longValue() != sp.getSwitchDPID())
-                            continue;
-                    }
-                    if (switchPort != null) {
-                        if (switchPort.intValue() != sp.getPort())
-                            continue;
-                    }
-                    match = true;
-                    break;
+            if (!match) return false;                
+        }
+        if (macAddress != null) {
+            if (macAddress.longValue() != next.getMACAddress())
+                return false;
+        }
+        if (vlan != null) {
+            Short[] vlans = next.getVlanId();
+            if (Arrays.binarySearch(vlans, vlan) < 0) 
+                return false;
+        }
+        if (ipv4Address != null) {
+            Integer[] ipv4Addresses = next.getIPv4Addresses();
+            if (Arrays.binarySearch(ipv4Addresses, ipv4Address) < 0) 
+                return false;
+        }
+        if (switchDPID != null || switchPort != null) {
+            SwitchPort[] sps = next.getAttachmentPoints();
+            if (sps == null) return false;
+            
+            match = false;
+            for (SwitchPort sp : sps) {
+                if (switchDPID != null) {
+                    if (switchDPID.longValue() != sp.getSwitchDPID())
+                        return false;
+                }
+                if (switchPort != null) {
+                    if (switchPort.intValue() != sp.getPort())
+                        return false;
                 }
-                if (!match) continue;
+                match = true;
+                break;
             }
-            return true;
+            if (!match) return false;
         }
-        return false;
+        return true;
     }
-
-    @Override
-    public Device next() {
-        if (hasNext()) {
-            Device cur = next;
-            next = null;
-            return cur;
-        }
-        throw new NoSuchElementException();
-    }
-
-    @Override
-    public void remove() {
-        throw new UnsupportedOperationException();
-    }
-
 }
diff --git a/src/main/java/net/floodlightcontroller/devicemanager/web/AbstractDeviceResource.java b/src/main/java/net/floodlightcontroller/devicemanager/web/AbstractDeviceResource.java
index 67a9db18dc0f6791dfcce6c2ef8bff0ba7f1bc30..58e79e49432764453b57af4dd7d1d61145c1bcc2 100644
--- a/src/main/java/net/floodlightcontroller/devicemanager/web/AbstractDeviceResource.java
+++ b/src/main/java/net/floodlightcontroller/devicemanager/web/AbstractDeviceResource.java
@@ -21,7 +21,10 @@ import java.util.Iterator;
 
 import net.floodlightcontroller.devicemanager.IDevice;
 import net.floodlightcontroller.devicemanager.IDeviceService;
+import net.floodlightcontroller.devicemanager.SwitchPort;
+import net.floodlightcontroller.devicemanager.internal.Device;
 import net.floodlightcontroller.packet.IPv4;
+import net.floodlightcontroller.util.FilterIterator;
 
 import org.openflow.util.HexString;
 import org.restlet.data.Form;
@@ -113,12 +116,82 @@ public abstract class AbstractDeviceResource extends ServerResource {
             }
         }
         
-        Iterator<? extends IDevice> diter =
+        @SuppressWarnings("unchecked")
+        Iterator<Device> diter = (Iterator<Device>)
                 deviceManager.queryDevices(macAddress, 
                                            vlan, 
                                            ipv4Address, 
                                            switchDPID, 
                                            switchPort);
-        return diter;
+        
+        final String macStartsWith = 
+                form.getFirstValue("mac__startswith", true);
+        final String vlanStartsWith = 
+                form.getFirstValue("vlan__startswith", true);
+        final String ipv4StartsWith = 
+                form.getFirstValue("ipv4__startswith", true);
+        final String dpidStartsWith = 
+                form.getFirstValue("dpid__startswith", true);
+        final String portStartsWith = 
+                form.getFirstValue("port__startswith", true);
+        
+        return new FilterIterator<Device>(diter) {
+            @Override
+            protected boolean matches(Device value) {
+                if (macStartsWith != null) {
+                    if (!value.getMACAddressString().startsWith(macStartsWith))
+                        return false;
+                }
+                if (vlanStartsWith != null) {
+                    boolean match = false;
+                    for (Short v : value.getVlanId()) {
+                        if (v != null && 
+                            v.toString().startsWith(vlanStartsWith)) {
+                            match = true;
+                            break;
+                        }
+                    }
+                    if (!match) return false;
+                }
+                if (ipv4StartsWith != null) {
+                    boolean match = false;
+                    for (Integer v : value.getIPv4Addresses()) {
+                        String str = IPv4.fromIPv4Address(v);
+                        if (v != null && 
+                            str.startsWith(ipv4StartsWith)) {
+                            match = true;
+                            break;
+                        }
+                    }
+                    if (!match) return false;
+                }
+                if (dpidStartsWith != null) {
+                    boolean match = false;
+                    for (SwitchPort v : value.getAttachmentPoints(true)) {
+                        String str = 
+                                HexString.toHexString(v.getSwitchDPID(), 8);
+                        if (v != null && 
+                            str.startsWith(dpidStartsWith)) {
+                            match = true;
+                            break;
+                        }
+                    }
+                    if (!match) return false;
+                }
+                if (portStartsWith != null) {
+                    boolean match = false;
+                    for (SwitchPort v : value.getAttachmentPoints(true)) {
+                        String str = Integer.toString(v.getPort());
+                        if (v != null && 
+                            str.startsWith(portStartsWith)) {
+                            match = true;
+                            break;
+                        }
+                    }
+                    if (!match) return false;
+                }
+                return true;
+            }
+        };
     }
 }
diff --git a/src/main/java/net/floodlightcontroller/util/FilterIterator.java b/src/main/java/net/floodlightcontroller/util/FilterIterator.java
new file mode 100644
index 0000000000000000000000000000000000000000..47cd5c9e2d4db4bb1dddaaa14eb7441e7058314f
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/util/FilterIterator.java
@@ -0,0 +1,80 @@
+/**
+*    Copyright 2012, Big Switch Networks, Inc. 
+*    Originally created by David Erickson, Stanford University
+* 
+*    Licensed under the Apache License, Version 2.0 (the "License"); you may
+*    not use this file except in compliance with the License. You may obtain
+*    a copy of the License at
+*
+*         http://www.apache.org/licenses/LICENSE-2.0
+*
+*    Unless required by applicable law or agreed to in writing, software
+*    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+*    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+*    License for the specific language governing permissions and limitations
+*    under the License.
+**/
+
+package net.floodlightcontroller.util;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/**
+ * An iterator that will filter values from an iterator and return only
+ * those values that match the predicate.
+ */
+public abstract class FilterIterator<T> implements Iterator<T> {
+    protected Iterator<T> subIterator;
+    protected T next;
+
+    /**
+     * Construct a filter iterator from the given sub iterator
+     * @param subIterator the sub iterator over which we'll filter
+     */
+    public FilterIterator(Iterator<T> subIterator) {
+        super();
+        this.subIterator = subIterator;
+    }
+
+    /**
+     * Check whether the given value should be returned by the
+     * filter
+     * @param value the value to check
+     * @return true if the value should be included
+     */
+    protected abstract boolean matches(T value);
+    
+    // ***********
+    // Iterator<T>
+    // ***********
+
+    @Override
+    public boolean hasNext() {
+        if (next != null) return true;
+        
+        while (subIterator.hasNext()) {
+            next = subIterator.next();
+            if (matches(next))
+                return true;
+        }
+        next = null;
+        return false;
+    }
+
+    @Override
+    public T next() {
+        if (hasNext()) {
+            T cur = next;
+            next = null;
+            return cur;
+        }
+        throw new NoSuchElementException();
+    }
+
+    @Override
+    public void remove() {
+        throw new UnsupportedOperationException();
+    }
+
+}