Unit tests for analytics internal API 58/3358/1
authorKatrina LaCurts <katrina.lacurts@plexxi.com>
Mon, 2 Dec 2013 17:45:13 +0000 (12:45 -0500)
committerKatrina LaCurts <katrina.lacurts@plexxi.com>
Mon, 2 Dec 2013 17:45:13 +0000 (12:45 -0500)
Signed-off-by: Katrina LaCurts <katrina.lacurts@plexxi.com>
analytics/api/src/main/java/org/opendaylight/affinity/analytics/IAnalyticsManager.java
analytics/implementation/src/main/java/org/opendaylight/affinity/analytics/internal/AnalyticsManager.java
analytics/implementation/src/test/java/org/opendaylight/affinity/analytics/internal/AnalyticsManagerTest.java

index 337f3570a95af75f7065b53e387cd70aaceeceb2..dd9dbd78679a44e70af540e352cda80c002d1611 100644 (file)
@@ -19,6 +19,8 @@ public interface IAnalyticsManager {
     // Host pair statistics
     long getByteCount(Host src, Host dst);
     long getByteCount(Host src, Host dst, Byte protocol);
+    double getDuration(Host src, Host dst);
+    double getDuration(Host src, Host dst, Byte protocol);
     double getBitRate(Host src, Host dst);
     double getBitRate(Host src, Host dst, Byte protocol);
     Map<Byte, Long> getAllByteCounts(Host src, Host dst);
@@ -27,6 +29,8 @@ public interface IAnalyticsManager {
     // AffinityLink statistics
     long getByteCount(AffinityLink al);
     long getByteCount(AffinityLink al, Byte protocol);
+    double getDuration(AffinityLink al);
+    double getDuration(AffinityLink al, Byte protocol);
     double getBitRate(AffinityLink al);
     double getBitRate(AffinityLink al, Byte protocol);
     Map<Byte, Long> getAllByteCounts(AffinityLink al);
@@ -35,6 +39,8 @@ public interface IAnalyticsManager {
     // Subnet statistics
     long getByteCount(String srcSubnet, String dstSubnet);
     long getByteCount(String srcSubnet, String dstSubnet, Byte protocol);
+    double getDuration(String srcSubnet, String dstSubnet);
+    double getDuration(String srcSubnet, String dstSubnet, Byte protocol);
     double getBitRate(String srcSubnet, String dstSubnet);
     double getBitRate(String srcSubnet, String dstSubnet, Byte protocol);
     Map<Byte, Long> getAllByteCounts(String srcSubnet, String dstSubnet);
index 6a025b68e5c691ba442f3996a1d4faaa57c27729..075d6ef925538b0029af65c7129f190557abdf3d 100644 (file)
@@ -173,7 +173,7 @@ public class AnalyticsManager implements IReadServiceListener, IAnalyticsManager
 
     /* Return the number of bytes transferred between two sets,
      * per-protocol (across all protocols if protocol is null).*/
-    private long getByteCount(Set<Host> srcSet, Set<Host> dstSet, Byte protocol) {
+    protected long getByteCount(Set<Host> srcSet, Set<Host> dstSet, Byte protocol) {
         long byteCount = 0;
         for (Host src : srcSet) {
             for (Host dst : dstSet) {
@@ -190,7 +190,7 @@ public class AnalyticsManager implements IReadServiceListener, IAnalyticsManager
     }
 
     /* Return all protocols used between two sets */
-    public Set<Byte> getProtocols(Set<Host> srcSet, Set<Host> dstSet) {
+    protected Set<Byte> getProtocols(Set<Host> srcSet, Set<Host> dstSet) {
         Set<Byte> protocols = new HashSet<Byte>();
         for (Host src : srcSet) {
             for (Host dst : dstSet) {
@@ -204,7 +204,7 @@ public class AnalyticsManager implements IReadServiceListener, IAnalyticsManager
     }
 
     /* Returns a map of all byte counts between two sets */
-    public Map<Byte, Long> getAllByteCounts(Set<Host> srcSet, Set<Host> dstSet) {
+    protected Map<Byte, Long> getAllByteCounts(Set<Host> srcSet, Set<Host> dstSet) {
         Map<Byte, Long> byteCounts = new HashMap<Byte, Long>();
         Set<Byte> protocols = getProtocols(srcSet, dstSet);
         for (Byte protocol : protocols)
@@ -215,11 +215,15 @@ public class AnalyticsManager implements IReadServiceListener, IAnalyticsManager
     /* Returns the duration of communication between two sets (max
      * duration of all flows) for a particular protocol (across all
      * protocols if protocol is null) */
-    public double getDuration(Set<Host> srcSet, Set<Host> dstSet, Byte protocol) {
+    protected double getDuration(Set<Host> srcSet, Set<Host> dstSet, Byte protocol) {
         double maxDuration = 0.0;
         for (Host src : srcSet) {
+            if (this.hostsToStats.get(src) == null)
+                continue;
             for (Host dst : dstSet) {
                 double duration;
+                if (this.hostsToStats.get(src).get(dst) == null)
+                    continue;
                 if (protocol == null)
                     duration = this.hostsToStats.get(src).get(dst).getDuration();
                 else
@@ -232,7 +236,7 @@ public class AnalyticsManager implements IReadServiceListener, IAnalyticsManager
     }
 
     /* Returns the bit rate between two sets */
-    public double getBitRate(Set<Host> srcSet, Set<Host> dstSet, Byte protocol) {
+    protected double getBitRate(Set<Host> srcSet, Set<Host> dstSet, Byte protocol) {
         double duration = getDuration(srcSet, dstSet, protocol);
         long totalBytes = getByteCount(srcSet, dstSet, protocol);
         if (duration == 0.0)
@@ -240,7 +244,7 @@ public class AnalyticsManager implements IReadServiceListener, IAnalyticsManager
         return (totalBytes * 8.0) / duration;
     }
 
-    public Map<Byte, Double> getAllBitRates(Set<Host> srcSet, Set<Host> dstSet) {
+    protected Map<Byte, Double> getAllBitRates(Set<Host> srcSet, Set<Host> dstSet) {
         Map<Byte, Double> bitRates = new HashMap<Byte, Double>();
         Set<Byte> protocols = getProtocols(srcSet, dstSet);
         for (Byte protocol : protocols)
@@ -266,6 +270,16 @@ public class AnalyticsManager implements IReadServiceListener, IAnalyticsManager
         return getAllByteCounts(srcSet, dstSet);
     }
 
+    public double getDuration(Host src, Host dst) {
+        return getDuration(src, dst, null);
+    }
+
+    public double getDuration(Host src, Host dst, Byte protocol) {
+        Set<Host> srcSet = new HashSet<Host>(Arrays.asList(src));
+        Set<Host> dstSet = new HashSet<Host>(Arrays.asList(dst));
+        return getDuration(srcSet, dstSet, protocol);
+    }
+
     public double getBitRate(Host src, Host dst) {
         return getBitRate(src, dst, null);
     }
@@ -298,6 +312,16 @@ public class AnalyticsManager implements IReadServiceListener, IAnalyticsManager
         return getAllByteCounts(srcSet, dstSet);
     }
 
+    public double getDuration(AffinityLink al) {
+        return getDuration(al, null);
+    }
+
+    public double getDuration(AffinityLink al, Byte protocol) {
+        Set<Host> srcSet = new HashSet<Host>(this.affinityManager.getAllElementsByHost(al.getToGroup()));
+        Set<Host> dstSet = new HashSet<Host>(this.affinityManager.getAllElementsByHost(al.getFromGroup()));
+        return getDuration(srcSet, dstSet, protocol);
+    }
+
     public double getBitRate(AffinityLink al) {
         return getBitRate(al, null);
     }
@@ -330,6 +354,16 @@ public class AnalyticsManager implements IReadServiceListener, IAnalyticsManager
         return getAllByteCounts(srcSet, dstSet);
     }
 
+    public double getDuration(String srcSubnet, String dstSubnet) {
+        return getDuration(srcSubnet, dstSubnet, null);
+    }
+
+    public double getDuration(String srcSubnet, String dstSubnet, Byte protocol) {
+        Set<Host> srcSet = getSrcHosts(srcSubnet, dstSubnet);
+        Set<Host> dstSet = getSrcHosts(dstSubnet, srcSubnet); // reverse arguments
+        return getDuration(srcSet, dstSet, protocol);
+    }
+
     public double getBitRate(String srcSubnet, String dstSubnet) {
         return getBitRate(srcSubnet, dstSubnet, null);
     }
@@ -347,15 +381,11 @@ public class AnalyticsManager implements IReadServiceListener, IAnalyticsManager
     }
 
     public Map<Host, Long> getIncomingHostByteCounts(String subnet) {
-        return getIncomingHostByteCountsInternal(subnet, null);
-    }
-
-    public Map<Host, Long> getIncomingHostByteCounts(String subnet, Byte protocol) {
-        return getIncomingHostByteCountsInternal(subnet, protocol);
+        return getIncomingHostByteCounts(subnet, null);
     }
 
     /* Returns all hosts that transferred data into this subnet. */
-    private Map<Host, Long> getIncomingHostByteCountsInternal(String subnet, Byte protocol) {
+    public Map<Host, Long> getIncomingHostByteCounts(String subnet, Byte protocol) {
         Map<Host, Long> hosts = new HashMap<Host, Long>();
         Set<Host> dstHosts = getHostsInSubnet(subnet);
         Set<Host> otherHosts = getHostsNotInSubnet(subnet);
index b0e6ec65da24ea175ceb0a6668b42646620e9d3b..2ca3dea5887b7e7b0029973b2d17d1d1459c3c8d 100644 (file)
@@ -21,6 +21,8 @@ import junit.framework.TestCase;
 import org.junit.Assert;\r
 import org.junit.Test;\r
 \r
+import org.opendaylight.affinity.affinity.AffinityGroup;\r
+import org.opendaylight.affinity.affinity.AffinityLink;\r
 import org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector;\r
 import org.opendaylight.controller.sal.core.ConstructionException;\r
 import org.opendaylight.controller.sal.core.Host;\r
@@ -114,6 +116,62 @@ public class AnalyticsManagerTest extends TestCase {
         }\r
     }\r
 \r
+    @Test public void testGetProtocols() {\r
+        AnalyticsManager am = new AnalyticsManager();\r
+        am.init();\r
+\r
+        try {\r
+            // Set up network\r
+            Node n1 = new Node(Node.NodeIDType.OPENFLOW, new Long(100L));\r
+            Node n2 = new Node(Node.NodeIDType.OPENFLOW, new Long(101L));\r
+            NodeConnector nc1 = new NodeConnector(NodeConnector.NodeConnectorIDType.OPENFLOW, new Short((short) 0xCAFC), n1);\r
+            NodeConnector nc2 = new NodeConnector(NodeConnector.NodeConnectorIDType.OPENFLOW, new Short((short) 0xCAFD), n2);\r
+            HostNodeConnector hnc1 = new HostNodeConnector(new byte[]{0,0,0,0,0,1}, InetAddress.getByName("10.0.0.1"), nc1, (short) 1);\r
+            HostNodeConnector hnc2 = new HostNodeConnector(new byte[]{0,0,0,0,0,2}, InetAddress.getByName("10.0.0.2"), nc2, (short) 1);\r
+            Set<HostNodeConnector> allHosts = new HashSet<HostNodeConnector>(Arrays.asList(hnc1, hnc2));\r
+            Set<Host> srcHosts = new HashSet<Host>(Arrays.asList(hnc1));\r
+            Set<Host> dstHosts = new HashSet<Host>(Arrays.asList(hnc2));\r
+\r
+            // Two flows between the nodes\r
+            Match match = new Match();\r
+            match.setField(new MatchField(MatchType.IN_PORT, nc1));\r
+            match.setField(new MatchField(MatchType.DL_DST, new byte[]{0,0,0,0,0,2}));\r
+            match.setField(new MatchField(MatchType.DL_TYPE, EtherTypes.IPv4.shortValue()));\r
+            match.setField(new MatchField(MatchType.NW_PROTO, IPProtocols.UDP.byteValue()));\r
+            Flow f = new Flow();\r
+            f.setMatch(match);\r
+            FlowOnNode fon = new FlowOnNode(f);\r
+            fon.setByteCount(200);\r
+            fon.setDurationSeconds(1);\r
+            List<FlowOnNode> flowStatsList = new ArrayList<FlowOnNode>();\r
+            flowStatsList.add(fon);\r
+\r
+            match = new Match();\r
+            match.setField(new MatchField(MatchType.IN_PORT, nc1));\r
+            match.setField(new MatchField(MatchType.DL_DST, new byte[]{0,0,0,0,0,2}));\r
+            match.setField(new MatchField(MatchType.DL_TYPE, EtherTypes.IPv4.shortValue()));\r
+            match.setField(new MatchField(MatchType.NW_PROTO, IPProtocols.TCP.byteValue()));\r
+            f = new Flow();\r
+            f.setMatch(match);\r
+            fon = new FlowOnNode(f);\r
+            fon.setByteCount(200);\r
+            fon.setDurationSeconds(1);\r
+            flowStatsList.add(fon);\r
+\r
+            am.nodeFlowStatisticsUpdated(n1, flowStatsList, allHosts);\r
+            Set<Byte> protocols = am.getProtocols(srcHosts, dstHosts);\r
+            Assert.assertTrue(protocols.size() == 2);\r
+            Assert.assertTrue(protocols.contains(IPProtocols.UDP.byteValue()));\r
+            Assert.assertTrue(protocols.contains(IPProtocols.TCP.byteValue()));\r
+        } catch (ConstructionException e) {\r
+            Assert.assertTrue(false);\r
+        } catch (UnknownHostException e ) {\r
+            Assert.assertTrue(false);\r
+        } finally {\r
+            am.destroy();\r
+        }\r
+    }\r
+\r
     @Test\r
     public void testSubnetMatching() {\r
 \r
@@ -199,80 +257,243 @@ public class AnalyticsManagerTest extends TestCase {
     }\r
 \r
     @Test\r
-    public void testGetStatsBetweenHosts() {\r
+    public void testStats() {\r
         AnalyticsManager am = new AnalyticsManager();\r
         am.init();\r
         try {\r
             // Set up the network\r
             Node n1 = new Node(Node.NodeIDType.OPENFLOW, new Long(100L));\r
             Node n2 = new Node(Node.NodeIDType.OPENFLOW, new Long(101L));\r
+            Node n3 = new Node(Node.NodeIDType.OPENFLOW, new Long(110L));\r
+            Node n4 = new Node(Node.NodeIDType.OPENFLOW, new Long(111L));\r
+            Node n5 = new Node(Node.NodeIDType.OPENFLOW, new Long(011L));\r
             NodeConnector nc1 = new NodeConnector(NodeConnector.NodeConnectorIDType.OPENFLOW, new Short((short) 0xCAFC), n1);\r
             NodeConnector nc2 = new NodeConnector(NodeConnector.NodeConnectorIDType.OPENFLOW, new Short((short) 0xCAFD), n2);\r
+            NodeConnector nc3 = new NodeConnector(NodeConnector.NodeConnectorIDType.OPENFLOW, new Short((short) 0xCAFE), n3);\r
+            NodeConnector nc4 = new NodeConnector(NodeConnector.NodeConnectorIDType.OPENFLOW, new Short((short) 0xCAFF), n4);\r
+            NodeConnector nc5 = new NodeConnector(NodeConnector.NodeConnectorIDType.OPENFLOW, new Short((short) 0xCAEF), n5);\r
             HostNodeConnector hnc1 = new HostNodeConnector(new byte[]{0,0,0,0,0,1}, InetAddress.getByName("10.0.0.1"), nc1, (short) 1);\r
             HostNodeConnector hnc2 = new HostNodeConnector(new byte[]{0,0,0,0,0,2}, InetAddress.getByName("10.0.0.2"), nc2, (short) 1);\r
-            Set<HostNodeConnector> allHosts = new HashSet<HostNodeConnector>(Arrays.asList(hnc1, hnc2));\r
+            HostNodeConnector hnc3 = new HostNodeConnector(new byte[]{0,0,0,0,0,3}, InetAddress.getByName("10.0.0.3"), nc3, (short) 1);\r
+            HostNodeConnector hnc4 = new HostNodeConnector(new byte[]{0,0,0,0,0,4}, InetAddress.getByName("10.0.0.4"), nc4, (short) 1);\r
+            HostNodeConnector hnc5 = new HostNodeConnector(new byte[]{0,0,0,0,0,5}, InetAddress.getByName("10.0.0.5"), nc5, (short) 1);\r
 \r
-            // Two flows between the hosts; different protocols\r
-            Match match1 = new Match();\r
-            match1.setField(new MatchField(MatchType.IN_PORT, nc1));\r
-            match1.setField(new MatchField(MatchType.DL_DST, new byte[]{0,0,0,0,0,2}));\r
-            match1.setField(new MatchField(MatchType.DL_TYPE, EtherTypes.IPv4.shortValue()));\r
-            match1.setField(new MatchField(MatchType.NW_PROTO, IPProtocols.ICMP.byteValue()));\r
-            Flow f1 = new Flow();\r
-            f1.setMatch(match1);\r
-            FlowOnNode fon1 = new FlowOnNode(f1);\r
-            fon1.setByteCount(200);\r
-            fon1.setDurationSeconds(1);\r
-            fon1.setDurationNanoseconds(100000000); // 1.1s\r
-            List<FlowOnNode> flowStatsList = new ArrayList<FlowOnNode>();\r
-            flowStatsList.add(fon1);\r
-\r
-            Match match2 = new Match();\r
-            match2.setField(new MatchField(MatchType.IN_PORT, nc1));\r
-            match2.setField(new MatchField(MatchType.DL_DST, new byte[]{0,0,0,0,0,2}));\r
-            match2.setField(new MatchField(MatchType.DL_TYPE, EtherTypes.IPv4.shortValue()));\r
-            match2.setField(new MatchField(MatchType.NW_PROTO, IPProtocols.UDP.byteValue()));\r
-            Flow f2 = new Flow();\r
-            f2.setMatch(match2);\r
-            FlowOnNode fon2 = new FlowOnNode(f2);\r
-            fon2.setByteCount(76);\r
-            fon2.setDurationSeconds(2);\r
-            fon2.setDurationNanoseconds(0);\r
-            flowStatsList.add(fon2);\r
-\r
-            // Basic stats\r
-            am.nodeFlowStatisticsUpdated(n1, flowStatsList, allHosts);\r
-            Assert.assertTrue(am.getByteCount(hnc1, hnc2) == 276);\r
-            Assert.assertTrue(am.getBitRate(hnc1, hnc2) == (276 * 8.0) / 2.0);\r
-\r
-            // Per-protocol stats\r
-            Assert.assertTrue(am.getByteCount(hnc1, hnc2, IPProtocols.ICMP.byteValue()) == 200);\r
-            Assert.assertTrue(am.getBitRate(hnc1, hnc2, IPProtocols.ICMP.byteValue()) == (200 * 8.0) / 1.1);\r
-            Assert.assertTrue(am.getByteCount(hnc1, hnc2, IPProtocols.UDP.byteValue()) == 76);\r
-            Assert.assertTrue(am.getBitRate(hnc1, hnc2, IPProtocols.UDP.byteValue()) == (76 * 8.0) / 2.0);\r
-            Assert.assertTrue(am.getByteCount(hnc1, hnc2, IPProtocols.TCP.byteValue()) == 0);\r
-            Assert.assertTrue(am.getBitRate(hnc1, hnc2, IPProtocols.TCP.byteValue()) == 0.0);\r
-\r
-            // All stats\r
-            Map<Byte, Long> byteCounts = am.getAllByteCounts(hnc1, hnc2);\r
-            Map<Byte, Double> bitRates = am.getAllBitRates(hnc1, hnc2);\r
-            Assert.assertTrue(byteCounts.get(IPProtocols.ICMP.byteValue()) == am.getByteCount(hnc1, hnc2, IPProtocols.ICMP.byteValue()));\r
-            Assert.assertTrue(bitRates.get(IPProtocols.ICMP.byteValue()) == am.getBitRate(hnc1, hnc2, IPProtocols.ICMP.byteValue()));\r
-            Assert.assertTrue(byteCounts.get(IPProtocols.UDP.byteValue()) == am.getByteCount(hnc1, hnc2, IPProtocols.UDP.byteValue()));\r
-            Assert.assertTrue(bitRates.get(IPProtocols.UDP.byteValue()) == am.getBitRate(hnc1, hnc2, IPProtocols.UDP.byteValue()));\r
+            Set<HostNodeConnector> allHosts = new HashSet<HostNodeConnector>(Arrays.asList(hnc1, hnc2, hnc3, hnc4, hnc5));\r
+            List<FlowOnNode> flowStatsListn1 = new ArrayList<FlowOnNode>();\r
+            List<FlowOnNode> flowStatsListn2 = new ArrayList<FlowOnNode>();\r
+\r
+            // 10.0.0.1 -> 10.0.0.3: 200Bytes over 1.1sec, UDP\r
+            Match match = new Match();\r
+            match.setField(new MatchField(MatchType.IN_PORT, nc1));\r
+            match.setField(new MatchField(MatchType.DL_DST, new byte[]{0,0,0,0,0,3}));\r
+            match.setField(new MatchField(MatchType.DL_TYPE, EtherTypes.IPv4.shortValue()));\r
+            match.setField(new MatchField(MatchType.NW_PROTO, IPProtocols.UDP.byteValue()));\r
+            Flow f = new Flow();\r
+            f.setMatch(match);\r
+            FlowOnNode fon = new FlowOnNode(f);\r
+            fon.setByteCount(200);\r
+            fon.setDurationSeconds(1);\r
+            fon.setDurationNanoseconds(100000000);\r
+            flowStatsListn1.add(fon);\r
+\r
+            // 10.0.0.1 -> 10.0.0.3: 64Bytes over 1sec, ICMP\r
+            match = new Match();\r
+            match.setField(new MatchField(MatchType.IN_PORT, nc1));\r
+            match.setField(new MatchField(MatchType.DL_DST, new byte[]{0,0,0,0,0,3}));\r
+            match.setField(new MatchField(MatchType.DL_TYPE, EtherTypes.IPv4.shortValue()));\r
+            match.setField(new MatchField(MatchType.NW_PROTO, IPProtocols.ICMP.byteValue()));\r
+            f = new Flow();\r
+            f.setMatch(match);\r
+            fon = new FlowOnNode(f);\r
+            fon.setByteCount(64);\r
+            fon.setDurationSeconds(1);\r
+            fon.setDurationNanoseconds(0);\r
+            flowStatsListn1.add(fon);\r
+\r
+            // 10.0.0.1 -> 10.0.0.4: 76Bytes over 2sec, TCP\r
+            match = new Match();\r
+            match.setField(new MatchField(MatchType.IN_PORT, nc1));\r
+            match.setField(new MatchField(MatchType.DL_DST, new byte[]{0,0,0,0,0,4}));\r
+            match.setField(new MatchField(MatchType.DL_TYPE, EtherTypes.IPv4.shortValue()));\r
+            match.setField(new MatchField(MatchType.NW_PROTO, IPProtocols.TCP.byteValue()));\r
+            f = new Flow();\r
+            f.setMatch(match);\r
+            fon = new FlowOnNode(f);\r
+            fon.setByteCount(76);\r
+            fon.setDurationSeconds(2);\r
+            fon.setDurationNanoseconds(0);\r
+            flowStatsListn1.add(fon);\r
+\r
+            // 10.0.0.2 -> 10.0.0.4: 300Bytes over 1.2sec, TCP\r
+            match = new Match();\r
+            match.setField(new MatchField(MatchType.IN_PORT, nc2));\r
+            match.setField(new MatchField(MatchType.DL_DST, new byte[]{0,0,0,0,0,4}));\r
+            match.setField(new MatchField(MatchType.DL_TYPE, EtherTypes.IPv4.shortValue()));\r
+            match.setField(new MatchField(MatchType.NW_PROTO, IPProtocols.TCP.byteValue()));\r
+            f = new Flow();\r
+            f.setMatch(match);\r
+            fon = new FlowOnNode(f);\r
+            fon.setByteCount(300);\r
+            fon.setDurationSeconds(1);\r
+            fon.setDurationNanoseconds(200000000);\r
+            flowStatsListn2.add(fon);\r
+\r
+            // 10.0.0.1 -> 10.0.0.5: 27Bytes over 1sec, UDP\r
+            match = new Match();\r
+            match.setField(new MatchField(MatchType.IN_PORT, nc1));\r
+            match.setField(new MatchField(MatchType.DL_DST, new byte[]{0,0,0,0,0,5}));\r
+            match.setField(new MatchField(MatchType.DL_TYPE, EtherTypes.IPv4.shortValue()));\r
+            match.setField(new MatchField(MatchType.NW_PROTO, IPProtocols.UDP.byteValue()));\r
+            f = new Flow();\r
+            f.setMatch(match);\r
+            fon = new FlowOnNode(f);\r
+            fon.setByteCount(27);\r
+            fon.setDurationSeconds(1);\r
+            fon.setDurationNanoseconds(0);\r
+            flowStatsListn1.add(fon);\r
+\r
+            // 10.0.0.2 -> 10.0.0.5: 234Bytes over 2sec, TCP\r
+            match = new Match();\r
+            match.setField(new MatchField(MatchType.IN_PORT, nc2));\r
+            match.setField(new MatchField(MatchType.DL_DST, new byte[]{0,0,0,0,0,5}));\r
+            match.setField(new MatchField(MatchType.DL_TYPE, EtherTypes.IPv4.shortValue()));\r
+            match.setField(new MatchField(MatchType.NW_PROTO, IPProtocols.TCP.byteValue()));\r
+            f = new Flow();\r
+            f.setMatch(match);\r
+            fon = new FlowOnNode(f);\r
+            fon.setByteCount(234);\r
+            fon.setDurationSeconds(2);\r
+            fon.setDurationNanoseconds(0);\r
+            flowStatsListn2.add(fon);\r
+\r
+            // 10.0.0.2 -> 10.0.0.5: 54Bytes over 3.1sec, ICMP\r
+            match = new Match();\r
+            match.setField(new MatchField(MatchType.IN_PORT, nc2));\r
+            match.setField(new MatchField(MatchType.DL_DST, new byte[]{0,0,0,0,0,5}));\r
+            match.setField(new MatchField(MatchType.DL_TYPE, EtherTypes.IPv4.shortValue()));\r
+            match.setField(new MatchField(MatchType.NW_PROTO, IPProtocols.ICMP.byteValue()));\r
+            f = new Flow();\r
+            f.setMatch(match);\r
+            fon = new FlowOnNode(f);\r
+            fon.setByteCount(54);\r
+            fon.setDurationSeconds(3);\r
+            fon.setDurationNanoseconds(100000000);\r
+            flowStatsListn2.add(fon);\r
+\r
+            am.nodeFlowStatisticsUpdated(n1, flowStatsListn1, allHosts);\r
+            am.nodeFlowStatisticsUpdated(n2, flowStatsListn2, allHosts);\r
+\r
+            // Host pairs - basic stats\r
+            Assert.assertTrue(am.getByteCount(hnc1, hnc3) == 200 + 64);\r
+            Assert.assertTrue(am.getDuration(hnc1, hnc3) == 1.1);\r
+            Assert.assertTrue(am.getBitRate(hnc1, hnc3) == ((200 + 64) * 8.0) / 1.1);\r
+            Assert.assertTrue(am.getByteCount(hnc1, hnc4) == 76);\r
+            Assert.assertTrue(am.getDuration(hnc1, hnc4) == 2.0);\r
+            Assert.assertTrue(am.getBitRate(hnc1, hnc4) == (76 * 8.0) / 2.0);\r
+            Assert.assertTrue(am.getByteCount(hnc2, hnc4) == 300);\r
+            Assert.assertTrue(am.getDuration(hnc2, hnc4) == 1.2);\r
+            Assert.assertTrue(am.getBitRate(hnc2, hnc4) == (300 * 8.0) / 1.2);\r
+            Assert.assertTrue(am.getByteCount(hnc1, hnc5) == 27);\r
+            Assert.assertTrue(am.getDuration(hnc1, hnc5) == 1.0);\r
+            Assert.assertTrue(am.getBitRate(hnc1, hnc5) == (27 * 8.0) / 1.0);\r
+            Assert.assertTrue(am.getByteCount(hnc2, hnc5) == 234 + 54);\r
+            Assert.assertTrue(am.getDuration(hnc2, hnc5) == 3.1);\r
+            Assert.assertTrue(am.getBitRate(hnc2, hnc5) == ((234 + 54) * 8.0) / 3.1);\r
+\r
+            // Host pairs - per-protocol stats\r
+            Assert.assertTrue(am.getByteCount(hnc1, hnc3, IPProtocols.ICMP.byteValue()) == 64);\r
+            Assert.assertTrue(am.getDuration(hnc1, hnc3, IPProtocols.ICMP.byteValue()) == 1.0);\r
+            Assert.assertTrue(am.getBitRate(hnc1, hnc3, IPProtocols.ICMP.byteValue()) == (64 * 8.0) / 1.0);\r
+            Assert.assertTrue(am.getByteCount(hnc1, hnc3, IPProtocols.UDP.byteValue()) == 200);\r
+            Assert.assertTrue(am.getDuration(hnc1, hnc3, IPProtocols.UDP.byteValue()) == 1.1);\r
+            Assert.assertTrue(am.getBitRate(hnc1, hnc3, IPProtocols.UDP.byteValue()) == (200 * 8.0) / 1.1);\r
+            Assert.assertTrue(am.getByteCount(hnc1, hnc3, IPProtocols.TCP.byteValue()) == 0);\r
+            Assert.assertTrue(am.getDuration(hnc1, hnc3, IPProtocols.TCP.byteValue()) == 0.0);\r
+            Assert.assertTrue(am.getBitRate(hnc1, hnc3, IPProtocols.TCP.byteValue()) == 0.0);\r
+            Assert.assertTrue(am.getByteCount(hnc1, hnc4, IPProtocols.TCP.byteValue()) == 76);\r
+            Assert.assertTrue(am.getDuration(hnc1, hnc4, IPProtocols.TCP.byteValue()) == 2.0);\r
+            Assert.assertTrue(am.getBitRate(hnc1, hnc4, IPProtocols.TCP.byteValue()) == (76 * 8.0) / 2.0);\r
+            Assert.assertTrue(am.getByteCount(hnc2, hnc4, IPProtocols.TCP.byteValue()) == 300);\r
+            Assert.assertTrue(am.getDuration(hnc2, hnc4, IPProtocols.TCP.byteValue()) == 1.2);\r
+            Assert.assertTrue(am.getBitRate(hnc2, hnc4, IPProtocols.TCP.byteValue()) == (300 * 8.0) / 1.2);\r
+            Assert.assertTrue(am.getByteCount(hnc1, hnc5, IPProtocols.UDP.byteValue()) == 27);\r
+            Assert.assertTrue(am.getDuration(hnc1, hnc5, IPProtocols.UDP.byteValue()) == 1.0);\r
+            Assert.assertTrue(am.getBitRate(hnc1, hnc5, IPProtocols.UDP.byteValue()) == (27 * 8.0) / 1.0);\r
+            Assert.assertTrue(am.getByteCount(hnc2, hnc5, IPProtocols.ICMP.byteValue()) == 54);\r
+            Assert.assertTrue(am.getDuration(hnc2, hnc5, IPProtocols.ICMP.byteValue()) == 3.1);\r
+            Assert.assertTrue(am.getBitRate(hnc2, hnc5, IPProtocols.ICMP.byteValue()) == (54 * 8.0) / 3.1);\r
+            Assert.assertTrue(am.getByteCount(hnc2, hnc5, IPProtocols.TCP.byteValue()) == 234);\r
+            Assert.assertTrue(am.getDuration(hnc2, hnc5, IPProtocols.TCP.byteValue()) == 2.0);\r
+            Assert.assertTrue(am.getBitRate(hnc2, hnc5, IPProtocols.TCP.byteValue()) == (234 * 8.0) / 2.0);\r
+\r
+            // Host pairs - all stats\r
+            Map<Byte, Long> byteCounts = am.getAllByteCounts(hnc1, hnc3);\r
+            Map<Byte, Double> bitRates = am.getAllBitRates(hnc1, hnc3);\r
+            Assert.assertTrue(byteCounts.get(IPProtocols.ICMP.byteValue()) == am.getByteCount(hnc1, hnc3, IPProtocols.ICMP.byteValue()));\r
+            Assert.assertTrue(byteCounts.get(IPProtocols.UDP.byteValue()) == am.getByteCount(hnc1, hnc3, IPProtocols.UDP.byteValue()));\r
             Assert.assertTrue(byteCounts.get(IPProtocols.TCP.byteValue()) == null);\r
+            Assert.assertTrue(bitRates.get(IPProtocols.ICMP.byteValue()) == am.getBitRate(hnc1, hnc3, IPProtocols.ICMP.byteValue()));\r
+            Assert.assertTrue(bitRates.get(IPProtocols.UDP.byteValue()) == am.getBitRate(hnc1, hnc3, IPProtocols.UDP.byteValue()));\r
             Assert.assertTrue(bitRates.get(IPProtocols.TCP.byteValue()) == null);\r
+            byteCounts = am.getAllByteCounts(hnc1, hnc4);\r
+            bitRates = am.getAllBitRates(hnc1, hnc4);\r
+            Assert.assertTrue(byteCounts.get(IPProtocols.TCP.byteValue()) == am.getByteCount(hnc1, hnc4, IPProtocols.TCP.byteValue()));\r
+            Assert.assertTrue(bitRates.get(IPProtocols.TCP.byteValue()) == am.getBitRate(hnc1, hnc4, IPProtocols.TCP.byteValue()));\r
+            byteCounts = am.getAllByteCounts(hnc2, hnc4);\r
+            bitRates = am.getAllBitRates(hnc2, hnc4);\r
+            Assert.assertTrue(byteCounts.get(IPProtocols.TCP.byteValue()) == am.getByteCount(hnc2, hnc4, IPProtocols.TCP.byteValue()));\r
+            Assert.assertTrue(bitRates.get(IPProtocols.TCP.byteValue()) == am.getBitRate(hnc2, hnc4, IPProtocols.TCP.byteValue()));\r
+            byteCounts = am.getAllByteCounts(hnc1, hnc5);\r
+            bitRates = am.getAllBitRates(hnc1, hnc5);\r
+            Assert.assertTrue(byteCounts.get(IPProtocols.UDP.byteValue()) == am.getByteCount(hnc1, hnc5, IPProtocols.UDP.byteValue()));\r
+            Assert.assertTrue(bitRates.get(IPProtocols.UDP.byteValue()) == am.getBitRate(hnc1, hnc5, IPProtocols.UDP.byteValue()));\r
+            byteCounts = am.getAllByteCounts(hnc2, hnc5);\r
+            bitRates = am.getAllBitRates(hnc2, hnc5);\r
+            Assert.assertTrue(byteCounts.get(IPProtocols.ICMP.byteValue()) == am.getByteCount(hnc2, hnc5, IPProtocols.ICMP.byteValue()));\r
+            Assert.assertTrue(byteCounts.get(IPProtocols.TCP.byteValue()) == am.getByteCount(hnc2, hnc5, IPProtocols.TCP.byteValue()));\r
+            Assert.assertTrue(bitRates.get(IPProtocols.ICMP.byteValue()) == am.getBitRate(hnc2, hnc5, IPProtocols.ICMP.byteValue()));\r
+            Assert.assertTrue(bitRates.get(IPProtocols.TCP.byteValue()) == am.getBitRate(hnc2, hnc5, IPProtocols.TCP.byteValue()));\r
+\r
+            // Host groups - basic stats\r
+            Set<Host> srcHosts = new HashSet<Host>(Arrays.asList(hnc1, hnc2));\r
+            Set<Host> dstHosts = new HashSet<Host>(Arrays.asList(hnc3, hnc4));\r
+            Assert.assertTrue(am.getByteCount(srcHosts, dstHosts, null) == 64 + 200 + 76 + 300);\r
+            Assert.assertTrue(am.getDuration(srcHosts, dstHosts, null) == 2.0);\r
+            Assert.assertTrue(am.getBitRate(srcHosts, dstHosts, null) == ((64 + 200 + 76 + 300) * 8.0) / 2.0);\r
+\r
+            // Host groups - per-protocol stats\r
+            Assert.assertTrue(am.getByteCount(srcHosts, dstHosts, IPProtocols.ICMP.byteValue()) == 64);\r
+            Assert.assertTrue(am.getDuration(srcHosts, dstHosts, IPProtocols.ICMP.byteValue()) == 1.0);\r
+            Assert.assertTrue(am.getBitRate(srcHosts, dstHosts, IPProtocols.ICMP.byteValue()) == (64 * 8.0) / 1.0);\r
+            Assert.assertTrue(am.getByteCount(srcHosts, dstHosts, IPProtocols.TCP.byteValue()) == 76 + 300);\r
+            Assert.assertTrue(am.getDuration(srcHosts, dstHosts, IPProtocols.TCP.byteValue()) == 2.0);\r
+            Assert.assertTrue(am.getBitRate(srcHosts, dstHosts, IPProtocols.TCP.byteValue()) == ((76 + 300) * 8.0) / 2.0);\r
+            Assert.assertTrue(am.getByteCount(srcHosts, dstHosts, IPProtocols.UDP.byteValue()) == 200);\r
+            Assert.assertTrue(am.getDuration(srcHosts, dstHosts, IPProtocols.UDP.byteValue()) == 1.1);\r
+            Assert.assertTrue(am.getBitRate(srcHosts, dstHosts, IPProtocols.UDP.byteValue()) == (200 * 8.0) / 1.1);\r
+\r
+            // Host groups - all stats\r
+            byteCounts = am.getAllByteCounts(srcHosts, dstHosts);\r
+            bitRates = am.getAllBitRates(srcHosts, dstHosts);\r
+            Assert.assertTrue(byteCounts.get(IPProtocols.ICMP.byteValue()) == am.getByteCount(srcHosts, dstHosts, IPProtocols.ICMP.byteValue()));\r
+            Assert.assertTrue(byteCounts.get(IPProtocols.UDP.byteValue()) == am.getByteCount(srcHosts, dstHosts, IPProtocols.UDP.byteValue()));\r
+            Assert.assertTrue(byteCounts.get(IPProtocols.TCP.byteValue()) == am.getByteCount(srcHosts, dstHosts, IPProtocols.TCP.byteValue()));\r
+            Assert.assertTrue(byteCounts.get(IPProtocols.ANY.byteValue()) == null);\r
+            Assert.assertTrue(bitRates.get(IPProtocols.ICMP.byteValue()) == am.getBitRate(srcHosts, dstHosts, IPProtocols.ICMP.byteValue()));\r
+            Assert.assertTrue(bitRates.get(IPProtocols.UDP.byteValue()) == am.getBitRate(srcHosts, dstHosts, IPProtocols.UDP.byteValue()));\r
+            Assert.assertTrue(bitRates.get(IPProtocols.TCP.byteValue()) == am.getBitRate(srcHosts, dstHosts, IPProtocols.TCP.byteValue()));\r
+            Assert.assertTrue(bitRates.get(IPProtocols.ANY.byteValue()) == null);\r
 \r
             // Correct flow over-writing\r
-            FlowOnNode fon3 = new FlowOnNode(f1);\r
-            fon3.setByteCount(300);\r
-            fon3.setDurationSeconds(3);\r
-            fon3.setDurationNanoseconds(100000000); // 3.1s\r
-            flowStatsList.add(fon3);\r
-            am.nodeFlowStatisticsUpdated(n2, flowStatsList, allHosts);\r
-            Assert.assertTrue(am.getByteCount(hnc1, hnc2) == 376);\r
-            Assert.assertTrue(am.getBitRate(hnc1, hnc2) == (376 * 8.0) / 3.1);\r
-            Assert.assertTrue(am.getByteCount(hnc1, hnc2, IPProtocols.ICMP.byteValue()) == 300);\r
+            fon = new FlowOnNode(f); // 10.0.0.2 -> 10.0.0.5, ICMP\r
+            fon.setByteCount(300);\r
+            fon.setDurationSeconds(4);\r
+            fon.setDurationNanoseconds(100000000);\r
+            flowStatsListn2.add(fon);\r
+            am.nodeFlowStatisticsUpdated(n2, flowStatsListn2, allHosts);\r
+            Assert.assertTrue(am.getByteCount(hnc2, hnc5) == 300 + 234);\r
+            Assert.assertTrue(am.getBitRate(hnc2, hnc5) == ((300 + 234) * 8.0) / 4.1);\r
+            Assert.assertTrue(am.getByteCount(hnc2, hnc5, IPProtocols.ICMP.byteValue()) == 300);\r
         } catch (ConstructionException e) {\r
             Assert.assertTrue(false);\r
         } catch (UnknownHostException e) {\r