/* * Copyright 2016 christopher.metter. * * 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 de.uniwuerzburg.info3.ofcprobe.vswitch.statistics; import java.io.File; import java.io.FileNotFoundException; import java.io.PrintWriter; import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.ListIterator; import de.uniwuerzburg.info3.ofcprobe.util.Util; import de.uniwuerzburg.info3.ofcprobe.vswitch.main.config.Config; import org.openflow.protocol.OFMessage; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * PacketsPerSecond Stats module * @author Christopher Metter(christopher.metter@informatik.uni-wuerzburg.de) * */ public class PacketsPerSecond implements IStatistics { /** * The Logger */ private static final Logger logger = LoggerFactory.getLogger(PacketsPerSecond.class); /** * The Total Counter Packets */ private int packets; /** * The Incoming Packets */ private int packetsI; /** * The Outgoing Packets */ private int packetsO; /** * FlowMods in Intervall */ private int fmInIntervall; /** * List of each Packets per Second */ private ArrayList<Integer> pps; /** * Incoming Packets = OFPACKET_OUT */ private ArrayList<Integer> ppsI; /** * Outgoing Packets = OPFPACKET_IN */ private ArrayList<Integer> ppsO; /** * Incoming FlowMod Packets */ private ArrayList<Integer> fmps; /** * Output File */ private String file; /** * Bool to handle Running/Stop state */ private boolean running; /** * PacketFormatter */ private static NumberFormat packetFormatter = new DecimalFormat("#000000"); /** * IntervallFormatter */ private static NumberFormat intervalFormatter = new DecimalFormat("#000"); /** * Counter incoming packet */ private int packI = 0; /** * Counter outgoing Packet */ private int packO = 0; /** * Counter flowMod packets */ private int fm = 0; /** * The Dpid */ private String dpid; /** * The startDate */ private Date startDate; private int lastIntervall; private int lastIntervallO; private int lastIntervallI; private int lastIntervallFM; /** * Constructor. */ public PacketsPerSecond(Config config){ int simulationTime = ((int) Math.floor(config.getSimTime() / 1000)) + 20; ArrayList<Integer> temp1 = new ArrayList<Integer>(); Util.ensureSize(temp1, simulationTime); this.pps = temp1; ArrayList<Integer> temp2 = new ArrayList<Integer>(); Util.ensureSize(temp2, simulationTime); this.ppsI = temp2; ArrayList<Integer> temp3 = new ArrayList<Integer>(); Util.ensureSize(temp3, simulationTime); this.ppsO = temp3; ArrayList<Integer> temp4 = new ArrayList<Integer>(); Util.ensureSize(temp4, simulationTime); this.fmps = temp4; this.packets = 0; this.packetsI = 0; this.packetsO = 0; this.fmInIntervall = 0; this.running = false; this.dpid = config.getSwitchConfig().getDPIDString(); this.startDate = new Date(); this.lastIntervall = 0; this.lastIntervallO = 0; this.lastIntervallI = 0; this.lastIntervallFM = 0; } /** * Processes next Packet */ private void nextPacket(Date now){ int intervall = Util.getIntervall(this.startDate, now); // Check for new Intervall if (intervall > this.lastIntervall) { Util.listSizeCheck(this.pps, intervall); this.pps.add(intervall - 1, this.pps.get(intervall -1) + this.packets); logger.info("[Switch#{}]: {} Packets in Interval#{}", this.dpid, packetFormatter.format(this.packets), intervalFormatter.format(intervall )); this.packets = 0; this.lastIntervall = intervall; } // increase number of packets in this interval this.packets++; } private void flowModIn() { this.fm++; Date now = new Date(); // nextPacket(now); int intervall = Util.getIntervall(this.startDate, now); if (intervall > this.lastIntervallFM) { Util.listSizeCheck(this.fmps, intervall); this.fmps.add(intervall - 1, this.fmps.get(intervall -1) + this.fmInIntervall); this.fmInIntervall=0; this.lastIntervallFM = intervall; } this.fmInIntervall++; } /** * PacketInProcessor */ private void packIn(){ this.packI++; Date now = new Date(); nextPacket(now); int intervall = Util.getIntervall(this.startDate, now); // Check for new Intervall if (intervall > this.lastIntervallI) { Util.listSizeCheck(this.ppsI, intervall); this.ppsI.add(intervall - 1, this.ppsI.get(intervall -1) + this.packetsI); logger.trace("[Switch#{}]: {} incoming Packets in Interval#{}", this.dpid, packetFormatter.format(this.packetsI), intervalFormatter.format(intervall)); this.packetsI = 0; this.lastIntervallI = intervall; } // increase number of packets in this interval this.packetsI++; } /** * PacketOUtProcessor */ private void packOut(){ this.packO++; Date now = new Date(); nextPacket(now); int intervall = Util.getIntervall(this.startDate, now); // Check for new Intervall if (intervall > this.lastIntervallO) { Util.listSizeCheck(this.ppsI, intervall); this.ppsO.add(intervall - 1, this.ppsO.get(intervall -1) + this.packetsO); logger.trace("[Switch#{}]: {} outgoing Packets in Interval#{}", this.dpid, packetFormatter.format(this.packetsO), intervalFormatter.format(intervall)); this.packetsO = 0; this.lastIntervallO = intervall; } // increase number of packets in this interval this.packetsO++; } /** * Process incoming Packets of this Switch * Only interested in OFPacketOut (Response from Controller to OFPacketIn) */ public void packetIn(OFMessage in) { if (!this.running) { return; } switch(in.getType()){ case BARRIER_REPLY: break; case BARRIER_REQUEST: break; case ECHO_REPLY: break; case ECHO_REQUEST: break; case ERROR: break; case FEATURES_REPLY: break; case FEATURES_REQUEST: break; case FLOW_MOD: flowModIn(); break; case FLOW_REMOVED: break; case GET_CONFIG_REPLY: break; case GET_CONFIG_REQUEST: break; case HELLO: break; case PACKET_IN: break; case PACKET_OUT: packIn(); break; case PORT_MOD: break; case PORT_STATUS: break; case QUEUE_CONFIG_REPLY: break; case QUEUE_CONFIG_REQUEST: break; case SET_CONFIG: break; case STATS_REPLY: break; case STATS_REQUEST: break; case VENDOR: break; default: break; } } /** * Process outgoing packets of this switch * Only interested in OFPacketIn (Generated by TrafficGen) */ public void packetOut(OFMessage out) { if (!this.running) { return; } switch(out.getType()){ case BARRIER_REPLY: break; case BARRIER_REQUEST: break; case ECHO_REPLY: break; case ECHO_REQUEST: break; case ERROR: break; case FEATURES_REPLY: break; case FEATURES_REQUEST: break; case FLOW_MOD: break; case FLOW_REMOVED: break; case GET_CONFIG_REPLY: break; case GET_CONFIG_REQUEST: break; case HELLO: break; case PACKET_IN: packOut(); break; case PACKET_OUT: break; case PORT_MOD: break; case PORT_STATUS: break; case QUEUE_CONFIG_REPLY: break; case QUEUE_CONFIG_REQUEST: break; case SET_CONFIG: break; case STATS_REPLY: break; case STATS_REQUEST: break; case VENDOR: break; default: break; } } /** * Ends this Session. */ public void report() { this.running = false; cleanupList(pps); cleanupList(ppsI); cleanupList(ppsO); cleanupList(fmps); double ppsMean = meanGetter(this.pps); logger.info("[Switch#{}]: Packets/Second Mean in this Session: {}", this.dpid, ppsMean); logger.info("[Switch#{}]: packO: {} - packI: {}", this.dpid, this.packO, this.packI); logger.info("[Switch#{}]: FlowMods: {}",this.dpid, this.fm); writeToFile(ppsMean); } private void cleanupList(List<Integer> list) { ListIterator<Integer> it = list.listIterator(list.size()); while (it.hasPrevious()) { if (it.previous()==0) { it.remove(); } else break; } } private double meanGetter(List<Integer> list){ double mean = 0; for (Integer uni : list ){ mean +=uni; } mean = mean/list.size(); if (Double.isNaN(mean)) { mean = 0.0; } return mean; } private void writeToFile(double ppsMean ) { try { File filou = new File(this.file); if (!filou.getParentFile().exists()) { filou.getParentFile().mkdirs(); } PrintWriter out = new PrintWriter(this.file); if (!this.pps.isEmpty()) { for (long pps : this.pps){ out.print(pps +";"); } } else { out.print("0;"); } out.print("\n"); out.print(ppsMean + ";" + meanGetter(this.ppsO) + ";" + meanGetter(this.ppsI)); out.print("\n"); if (!this.ppsO.isEmpty()) { for (long ppsO : this.ppsO){ out.print(ppsO +";"); } } else { out.print("0;"); } out.print("\n"); if (!this.ppsI.isEmpty()) { for (long ppsI : this.ppsI){ out.print(ppsI +";"); } } else { out.print("0;"); } out.close(); } catch (FileNotFoundException e) { logger.debug("[Switch#{}]: {}", this.dpid, e); } } @Override public void setReportFile(String file) { this.file = file; } @Override public void evaluate() { // Auto-generated method stub } @Override public void start() { this.startDate = new Date(); this.running = true; } @Override public void stop() { // this.running = false; } }