/** * Getter for getting the payload length for the provided burst. * * @param burst * @param bIncludeBkgApp * @return */ private int getPayloadLength(Burst burst, boolean bIncludeBkgApp) { int r = 0; for (PacketInfo p : burst.getPackets()) { if (bIncludeBkgApp || p.getAppName() != null) { r += p.getPayloadLen(); } } return r; }
/** Method to assign the burst states. */ private void analyzeBursts() { List<UserEvent> userEvents = analysis.getUserEvents(); List<CpuActivity> cpuEvents = analysis.getCpuActivityList(); int userEventsSize = userEvents.size(); int cpuEventsSize = cpuEvents.size(); int userEventPointer = 0; int cpuPointer = 0; // Analyze each burst Burst b = null; Burst lastBurst; for (Iterator<Burst> i = burstCollection.iterator(); i.hasNext(); ) { lastBurst = b; b = i.next(); // Step 1: Remove background packets List<PacketInfo> pktIdx = new ArrayList<PacketInfo>(b.getPackets().size()); int payloadLen = 0; Set<TcpInfo> tcpInfo = new HashSet<TcpInfo>(); for (PacketInfo p : b.getPackets()) { if (p.getAppName() != null) { payloadLen += p.getPayloadLen(); pktIdx.add(p); TcpInfo tcp = p.getTcpInfo(); if (tcp != null) { tcpInfo.add(tcp); } } } if (pktIdx.size() == 0) { assert (payloadLen == 0); b.addBurstInfo(BurstInfo.BURST_BKG); continue; } PacketInfo pkt0 = pktIdx.get(0); TcpInfo info0 = pkt0.getTcpInfo(); double time0 = pkt0.getTimeStamp(); // Step 2: a long burst? if (b.getEndTime() - b.getBeginTime() > profile.getLargeBurstDuration() && payloadLen > profile.getLargeBurstSize()) { b.addBurstInfo(BurstInfo.BURST_LONG); ++longBurstCount; continue; } // Step 3: Contains no payload? if (payloadLen == 0) { if (tcpInfo.contains(TcpInfo.TCP_CLOSE)) { b.addBurstInfo(BurstInfo.BURST_FIN); } if (tcpInfo.contains(TcpInfo.TCP_ESTABLISH)) { b.addBurstInfo(BurstInfo.BURST_SYN); } if (tcpInfo.contains(TcpInfo.TCP_RESET)) { b.addBurstInfo(BurstInfo.BURST_RST); } if (tcpInfo.contains(TcpInfo.TCP_KEEP_ALIVE) || tcpInfo.contains(TcpInfo.TCP_KEEP_ALIVE_ACK)) { b.addBurstInfo(BurstInfo.BURST_KEEPALIVE); } if (tcpInfo.contains(TcpInfo.TCP_ZERO_WINDOW)) { b.addBurstInfo(BurstInfo.BURST_ZEROWIN); } if (tcpInfo.contains(TcpInfo.TCP_WINDOW_UPDATE)) { b.addBurstInfo(BurstInfo.BURST_WINUPDATE); } if (b.getBurstInfos().size() == 0 && (info0 == TcpInfo.TCP_ACK_RECOVER || info0 == TcpInfo.TCP_ACK_DUP)) { b.addBurstInfo(BurstInfo.BURST_LOSS_RECOVER); } if (b.getBurstInfos().size() > 0) continue; } // Step 4: Server delay if (pkt0.getDir() == PacketInfo.Direction.DOWNLINK && (info0 == TcpInfo.TCP_DATA || info0 == TcpInfo.TCP_ACK)) { b.addBurstInfo(BurstInfo.BURST_SERVER_DELAY); continue; } // Step 5: Loss recover if (info0 == TcpInfo.TCP_ACK_DUP || info0 == TcpInfo.TCP_DATA_DUP) { b.addBurstInfo(BurstInfo.BURST_LOSS_DUP); continue; } if (info0 == TcpInfo.TCP_DATA_RECOVER || info0 == TcpInfo.TCP_ACK_RECOVER) { b.addBurstInfo(BurstInfo.BURST_LOSS_RECOVER); continue; } // Step 6: User triggered final double USER_EVENT_SMALL_TOLERATE = profile.getUserInputTh(); if (payloadLen > 0) { UserEvent ue = null; while ((userEventPointer < userEventsSize) && ((ue = userEvents.get(userEventPointer)).getReleaseTime() < (time0 - USER_EVENT_TOLERATE))) ++userEventPointer; BurstInfo bi = ue != null ? ((ue.getEventType() == UserEventType.SCREEN_LANDSCAPE || ue.getEventType() == UserEventType.SCREEN_PORTRAIT) ? BurstInfo.BURST_SCREEN_ROTATION_INPUT : BurstInfo.BURST_USER_INPUT) : null; int j = userEventPointer; double minGap = Double.MAX_VALUE; while (j < userEventsSize) { UserEvent uEvent = userEvents.get(j); if (withinTolerate(uEvent.getPressTime(), time0)) { double gap = time0 - uEvent.getPressTime(); if (gap < minGap) { minGap = gap; } } if (withinTolerate(uEvent.getReleaseTime(), time0)) { double gap = time0 - uEvent.getReleaseTime(); if (gap < minGap) { minGap = gap; } } if (uEvent.getPressTime() > time0) { break; } j++; } if (minGap < USER_EVENT_SMALL_TOLERATE) { b.addBurstInfo(bi); continue; } else if (minGap < USER_EVENT_TOLERATE && (lastBurst == null || lastBurst.getEndTime() < b.getBeginTime() - minGap)) { double cpuBegin = time0 - minGap; double cpuEnd = time0; // Check CPU usage while (cpuPointer < cpuEventsSize) { double t = cpuEvents.get(cpuPointer).getBeginTimeStamp(); if (t < b.getBeginTime() - USER_EVENT_TOLERATE) { ++cpuPointer; } else { break; } } int k = cpuPointer; double s = 0.0f; int ns = 0; while (k < cpuEventsSize) { CpuActivity cpuAct = cpuEvents.get(k); double t = cpuAct.getBeginTimeStamp(); if (t > cpuBegin && t < cpuEnd) { s += cpuAct.getUsage(); ns++; } if (t >= cpuEnd) { break; } k++; } if (ns > 0 && (s / ns) > AVG_CPU_USAGE_THRESHOLD) { b.addBurstInfo(bi); b.addBurstInfo(BurstInfo.BURST_CPU_BUSY); continue; } } } // Step 7: Client delay if (b.getBurstInfos().size() == 0 && payloadLen == 0) { b.addBurstInfo(BurstInfo.BURST_UNKNOWN); } else { b.addBurstInfo(BurstInfo.BURST_CLIENT_DELAY); } } }
/** Burst data's analyzed to categorize the periodic bursts. */ private void diagnosisPeriodicRequest() { Map<String, List<Double>> requestHost2tsList = new HashMap<String, List<Double>>(); Map<String, List<Double>> requestObj2tsList = new HashMap<String, List<Double>>(); Map<InetAddress, List<Double>> connIP2tsList = new HashMap<InetAddress, List<Double>>(); Set<String> hostPeriodicInfoSet = new HashSet<String>(); periodicCount = 0; diffPeriodicCount = 0; minimumPeriodicRepeatTime = 0.0; for (TCPSession b : analysis.getTcpSessions()) { // Get a list of timestamps of established sessions with each remote // IP PacketInfo p = b.getPackets().get(0); if (p.getTcpInfo() == TcpInfo.TCP_ESTABLISH) { List<Double> res = connIP2tsList.get(b.getRemoteIP()); if (res == null) { res = new ArrayList<Double>(); connIP2tsList.put(b.getRemoteIP(), res); } res.add(Double.valueOf(p.getTimeStamp())); } // Get a list of timestamps of HTTP requests to hosts/object names for (HttpRequestResponseInfo rr : b.getRequestResponseInfo()) { PacketInfo pkt = rr.getFirstDataPacket(); if (rr.getDirection() == HttpRequestResponseInfo.Direction.REQUEST) { Double ts0 = Double.valueOf(pkt.getTimeStamp()); if (rr.getHostName() != null) { List<Double> tempRequestHostEventList = requestHost2tsList.get(rr.getHostName()); if (tempRequestHostEventList == null) { tempRequestHostEventList = new ArrayList<Double>(); requestHost2tsList.put(rr.getHostName(), tempRequestHostEventList); } tempRequestHostEventList.add(ts0); } if (rr.getObjName() != null) { String objName = rr.getObjNameWithoutParams(); List<Double> tempRequestObjEventList = requestObj2tsList.get(objName); if (tempRequestObjEventList == null) { tempRequestObjEventList = new ArrayList<Double>(); requestObj2tsList.put(objName, tempRequestObjEventList); } tempRequestObjEventList.add(ts0); } } } } Set<String> hostList = new HashSet<String>(); for (Map.Entry<String, List<Double>> iter : requestHost2tsList.entrySet()) { if (SelfCorr(iter.getValue())) { hostList.add(iter.getKey()); } } Set<String> objList = new HashSet<String>(); for (Map.Entry<String, List<Double>> iter : requestObj2tsList.entrySet()) { if (SelfCorr(iter.getValue())) { objList.add(iter.getKey()); } } Set<InetAddress> ipList = new HashSet<InetAddress>(); for (Map.Entry<InetAddress, List<Double>> iter : connIP2tsList.entrySet()) { if (SelfCorr(iter.getValue())) { ipList.add(iter.getKey()); } } for (Burst burst : burstCollection) { if (!burst.getBurstInfos().contains(BurstInfo.BURST_CLIENT_DELAY)) { continue; } Packet beginPacket = burst.getBeginPacket().getPacket(); if (beginPacket instanceof IPPacket) { IPPacket ip = (IPPacket) beginPacket; if (ipList.contains(ip.getDestinationIPAddress()) || ipList.contains(ip.getSourceIPAddress())) { periodicCount++; burst.setBurstInfo(BurstInfo.BURST_PERIODICAL); if (ipList.contains(ip.getDestinationIPAddress())) { hostPeriodicInfoSet.add(ip.getDestinationIPAddress().toString()); } else { hostPeriodicInfoSet.add(ip.getSourceIPAddress().toString()); } continue; } } PacketInfo firstUplinkPayloadPacket = null; for (PacketInfo p : burst.getPackets()) { if (p.getDir() == Direction.UPLINK && p.getPayloadLen() > 0) { firstUplinkPayloadPacket = p; break; } } for (TCPSession session : analysis.getTcpSessions()) { for (HttpRequestResponseInfo rr : session.getRequestResponseInfo()) { if (rr.getDirection() == HttpRequestResponseInfo.Direction.REQUEST && (hostList.contains(rr.getHostName()) || objList.contains(rr.getObjNameWithoutParams()))) { if (rr.getFirstDataPacket() == firstUplinkPayloadPacket) { periodicCount++; burst.setBurstInfo(BurstInfo.BURST_PERIODICAL); burst.setFirstUplinkDataPacket(firstUplinkPayloadPacket); if (hostList.contains(rr.getHostName())) { hostPeriodicInfoSet.add(rr.getHostName()); } else { hostPeriodicInfoSet.add(rr.getObjNameWithoutParams()); } continue; } } } } } diffPeriodicCount = hostPeriodicInfoSet.size(); }
/** Groups packets into Burst Collections */ private void groupIntoBursts() { // Validate that there are packets List<PacketInfo> packets = this.analysis.getPackets(); if (packets.size() <= 0) { this.burstCollection = Collections.emptyList(); return; } ArrayList<Burst> result = new ArrayList<Burst>(); double burstThresh = profile.getBurstTh(); double longBurstThresh = profile.getLongBurstTh(); List<PacketInfo> burstPackets = new ArrayList<PacketInfo>(); // Step 1: Build bursts using burst time threshold PacketInfo lastPacket = null; for (PacketInfo packet : packets) { if (lastPacket == null || (packet.getTimeStamp() - lastPacket.getTimeStamp() > burstThresh && !mss.contains(lastPacket.getPayloadLen()))) { if (burstPackets.size() > 0) { result.add(new Burst(burstPackets)); burstPackets.clear(); } } burstPackets.add(packet); lastPacket = packet; } result.add(new Burst(burstPackets)); // Step 2: Remove promotion delays and merge bursts if possible Map<PacketInfo, Double> timestampList = normalizeCore(packets); List<Burst> newBurstColl = new ArrayList<Burst>(result.size()); int n = result.size(); Burst newBurst = result.get(0); for (int i = 0; i < n - 1; i++) { Burst bnext = result.get(i + 1); double time1 = timestampList.get(newBurst.getEndPacket()); double time2 = timestampList.get(bnext.getBeginPacket()); if ((time2 - time1) < burstThresh) { newBurst.merge(bnext); } else { newBurstColl.add(newBurst); newBurst = bnext; } } newBurstColl.add(newBurst); this.burstCollection = newBurstColl; // Step 3: compute burstID for each packet n = burstCollection.size(); for (Burst b : burstCollection) { for (PacketInfo p : b.getPackets()) { p.setBurst(b); } } // Step 4: determine short/long IBTs n = burstCollection.size(); for (int i = 0; i < n; i++) { Burst b = burstCollection.get(i); assert (b.getEndTime() >= b.getBeginTime()); if (i < n - 1) { double ibt = burstCollection.get(i + 1).getBeginTime() - b.getEndTime(); assert (ibt >= burstThresh); b.setbLong((ibt > longBurstThresh)); } else { b.setbLong(true); } } }