/*
* ** Network and Service Differentiation Extensions to CloudSim 3.0 **
*
* Gokul Poduval & Chen-Khong Tham
* Computer Communication Networks (CCN) Lab
* Dept of Electrical & Computer Engineering
* National University of Singapore
* August 2004
*
* Licence: GPL - http://www.gnu.org/copyleft/gpl.html
* Copyright (c) 2004, The University of Melbourne, Australia and National
* University of Singapore
* InfoPacket.java - Implementation of a Information Packet.
*
*/
package org.cloudbus.cloudsim;
import java.text.DecimalFormat;
import java.util.Vector;
import org.cloudbus.cloudsim.core.CloudSim;
import org.cloudbus.cloudsim.core.CloudSimTags;
/**
* 遍历网络收集信息,类似于ping
* InfoPacket class can be used to gather information from the network layer.
* An InfoPacket traverses the network topology similar to a
* {@link gridsim.net.NetPacket},
* but it collects information like bandwidths, and Round Trip Time etc. It is
* the equivalent of ICMP in physical networks.
* <p>
* You can set all the parameters to an InfoPacket that can be applied to a
* NetPacket. So if you want to find out the kind of information that a
* particular type of NetPacket is experiencing, set the size and network
* class of an InfoPacket to the same as the NetPacket, and send it to the same
* destination from the same source.
*
* @author Gokul Poduval
* @author Chen-Khong Tham, National University of Singapore
* @since CloudSim Toolkit 1.0
*/
public class InfoPacket implements Packet {
/** The name. */
private final String name; // packet name
/** The size. */
private long size; // size of this packet
/** The packet id. */
private final int packetId; // id of this packet
/** The src id. */
private final int srcId; // original sender id
/** The dest id. */
private int destId; // destination id
/** The last. */
private int last; // last hop
/** The tag. */
private int tag; // whether going or returning
/** The hops number. */
private int hopsNumber; // number of hops
/** The ping size. */
private long pingSize; // original ping size
/** The net service type. */
private int netServiceType; // level of service type
/** The bandwidth. */
private double bandwidth; // bottleneck
/** The entities. */
private Vector<Integer> entities; // list of entity IDs
/** The entry times. */
private Vector<Double> entryTimes; // list of entry times
/** The exit times. */
private Vector<Double> exitTimes; // list of exit times
/** The baud rates. */
private Vector<Double> baudRates; // list of entity's baud rate
/** The num. */
private DecimalFormat num; // formatting the decimal points
/**
* Constructs a new Information packet.
*
* @param name Name of this packet
* @param packetID The ID of this packet
* @param size size of the packet
* @param srcID The ID of the entity that sends out this packet
* @param destID The ID of the entity to which this packet is destined
* @param netServiceType the class of traffic this packet belongs to
*
* @pre name != null
* @post $none
*/
public InfoPacket(String name, int packetID, long size, int srcID,
int destID, int netServiceType) {
this.name = name;
this.packetId = packetID;
this.srcId = srcID;
this.destId = destID;
this.size = size;
this.netServiceType = netServiceType;
init();
}
/**
* Initialises common attributes.
*
* @pre $none
* @post $none
*/
private void init() {
this.last = srcId;
this.tag = CloudSimTags.INFOPKT_SUBMIT;
this.bandwidth = -1;
this.hopsNumber = 0;
this.pingSize = this.size;
if (name != null) {
this.entities = new Vector<Integer>();
this.entryTimes = new Vector<Double>();
this.exitTimes = new Vector<Double>();
this.baudRates = new Vector<Double>();
num = new DecimalFormat("#0.000#"); // 4 decimal spaces
}
}
/**
* Returns the ID of this packet.
*
* @return packet ID
*
* @pre $none
* @post $none
*/
@Override
public int getId() {
return packetId;
}
/**
* Sets original size of ping request.
*
* @param size ping data size (in bytes)
*
* @pre size >= 0
* @post $none
*/
public void setOriginalPingSize(long size) {
this.pingSize = size;
}
/**
* Gets original size of ping request.
*
* @return original size
*
* @pre $none
* @post $none
*/
public long getOriginalPingSize() {
return pingSize;
}
/**
* 转换成字符串形式
* Returns a human-readable information of this packet.
*
* @return description of this packet
*
* @pre $none
* @post $none
*/
@Override
public String toString() {
if (name == null) {
return "Empty InfoPacket that contains no ping information.";
}
int SIZE = 1000; // number of chars
StringBuffer sb = new StringBuffer(SIZE);
sb.append("Ping information for " + name + "\n");
sb.append("Entity Name\tEntry Time\tExit Time\t Bandwidth\n");
sb.append("----------------------------------------------------------\n");
String tab = " "; // 4 spaces
for (int i = 0 ; i < entities.size(); i++)
{
int resID = entities.get(i).intValue();
sb.append(CloudSim.getEntityName(resID) + "\t\t");
String entry = getData(entryTimes, i);
String exit = getData(exitTimes, i);
String bw = getData(baudRates, i);
sb.append(entry + tab + tab + exit + tab + tab + bw + "\n");
}
sb.append("\nRound Trip Time : " +
num.format(this.getTotalResponseTime()) );
sb.append(" seconds");
sb.append("\nNumber of Hops : " + this.getNumHop() );
sb.append("\nBottleneck Bandwidth : " + bandwidth + " bits/s");
return sb.toString();
}
/**
* 获得有关的数据
* Gets relevant data from a list.
*
* @param v a list
* @param index the location in a list
*
* @return the data
*
* @pre v != null
* @post index > 0
*/
private String getData(Vector<Double> v, int index) {
String result;
try {
Double obj = v.get(index);
double id = obj.doubleValue();
result = num.format(id);
} catch (Exception e) {
result = " N/A";
}
return result;
}
/**
* Gets the size of this packet.
*
* @return size of the packet.
*
* @pre $none
* @post $none
*/
@Override
public long getSize() {
return size;
}
/**
* Sets the size of this packet.
*
* @param size size of the packet
*
* @return <tt>true</tt> if it is successful, <tt>false</tt> otherwise
*
* @pre size >= 0
* @post $none
*/
@Override
public boolean setSize(long size) {
if (size < 0) {
return false;
}
this.size = size;
return true;
}
/**
* Gets the id of the entity to which the packet is destined.
*
* @return the desination ID
*
* @pre $none
* @post $none
*/
@Override
public int getDestId() {
return destId;
}
/**
* Gets the id of the entity that sent out this packet.
*
* @return the source ID
*
* @pre $none
* @post $none
*/
@Override
public int getSrcId() {
return srcId;
}
/**
* 获得跳点数
* Returns the number of hops that this packet has traversed. Since the
* packet takes a round trip, the same router may have been traversed
* twice.
*
* @return the number of hops this packet has traversed
*
* @pre $none
* @post $none
*/
public int getNumHop() {
int PAIR = 2;
return ((hopsNumber - PAIR) + 1) / PAIR; //目标一次,src两次不算
}
/**
* packet在网络中的时间
* Gets the total time that this packet has spent in the network. This is
* basically the RTT. Dividing this by half should be the approximate
* latency.
* <p>
* RTT is taken as the final entry time - first exit time.
*
* @return total round time
*
* @pre $none
* @post $none
*/
public double getTotalResponseTime() {
if (exitTimes == null || entryTimes == null) {
return 0;
}
double time = 0;
try {
double startTime = exitTimes.firstElement().doubleValue();
double receiveTime = entryTimes.lastElement().doubleValue();
time = receiveTime - startTime;
} catch (Exception e) {
time = 0;
}
return time;
}
/**
* Returns the bottleneck bandwidth between the source and the destination.
*
* @return the bottleneck bandwidth
*
* @pre $none
* @post $none
*/
public double getBaudRate() {
return bandwidth;
}
/**
* This method should be called by network entities that count as hops, for
* e.g. Routers or CloudResources. It should not be called by links etc.
*
* @param id the id of the hop that this InfoPacket is traversing
*
* @pre id > 0
* @post $none
*/
public void addHop(int id) {
if (entities == null) {
return;
}
hopsNumber++;
entities.add(Integer.valueOf(id));
}
/**
* 进入时间
* This method should be called by routers and other entities
* when this InfoPacket reaches them along with the current simulation time.
*
* @param time current simulation time, use
* {@link gridsim.CloudSim#clock()} to obtain this
*
* @pre time >= 0
* @post $none
*/
public void addEntryTime(double time) {
if (entryTimes == null) {
return;
}
if (time < 0) {
time = 0.0;
}
entryTimes.add(Double.valueOf(time));
}
/**
* 离开时间
* This method should be called by routers and other entities
* when this InfoPacket is leaving them. It should also supply the current
* simulation time.
*
* @param time current simulation time, use
* {@link gridsim.CloudSim#clock()} to obtain this
*
* @pre time >= 0
* @post $none
*/
public void addExitTime(double time) {
if (exitTimes == null) {
return;
}
if (time < 0) {
time = 0.0;
}
exitTimes.add(Double.valueOf(time));
}
/**
* 添加波特率
* Every entity that the InfoPacket traverses should add the baud rate of
* the link on which this packet will be sent out next.
*
* @param baudRate the entity's baud rate in bits/s
*
* @pre baudRate > 0
* @post $none
*/
public void addBaudRate(double baudRate) {
if (baudRates == null) {
return;
}
baudRates.add(new Double(baudRate));
if (bandwidth < 0 || baudRate < this.bandwidth) {
this.bandwidth = baudRate;
}
}
/**
* Returns the list of all the bandwidths that this packet has traversed.
*
* @return a Double Array of links bandwidths
*
* @pre $none
* @post $none
*/
public Object[] getDetailBaudRate() {
if (baudRates == null) {
return null;
}
return baudRates.toArray();
}
/**
* Returns the list of all the hops that this packet has traversed.
*
* @return an Integer Array of hop ids
*
* @pre $none
* @post $none
*/
public Object[] getDetailHops() {
if (entities == null) {
return null;
}
return entities.toArray();
}
/**
* Returns the list of all entry time that this packet has traversed.
*
* @return an Integer Array of entry time
*
* @pre $none
* @post $none
*/
public Object[] getDetailEntryTimes() {
if (entryTimes == null) {
return null;
}
return entryTimes.toArray();
}
/**
* Returns the list of all exit time that this packet has traversed.
*
* @return an Integer Array of exit time
*
* @pre $none
* @post $none
*/
public Object[] getDetailExitTimes() {
if (exitTimes == null) {
return null;
}
return exitTimes.toArray();
}
/**
* Gets an entity ID from the last hop that this packet has traversed.
*
* @return an entity ID
*
* @pre $none
* @post $none
*/
@Override
public int getLast() {
return last;
}
/**
* Sets an entity ID from the last hop that this packet has traversed.
*
* @param last an entity ID from the last hop
*
* @pre last > 0
* @post $none
*/
@Override
public void setLast(int last) {
this.last = last;
}
/**
* Gets the network service type of this packet.
*
* @return the network service type
*
* @pre $none
* @post $none
*/
@Override
public int getNetServiceType() {
return netServiceType ;
}
/**
* Sets the network service type of this packet.
*
* @param netServiceType the packet's network service type
*
* @pre netServiceType >= 0
* @post $none
*/
@Override
public void setNetServiceType(int netServiceType) {
this.netServiceType = netServiceType ;
}
/**
* Gets this packet tag.
*
* @return this packet tag
*
* @pre $none
* @post $none
*/
@Override
public int getTag() {
return tag ;
}
/**
* Sets the tag of this packet.
*
* @param tag the packet's tag
*
* @return <tt>true</tt> if successful, <tt>false</tt> otherwise
*
* @pre tag > 0
* @post $none
*/
public boolean setTag(int tag) {
boolean flag = false;
switch (tag) {
case CloudSimTags.INFOPKT_SUBMIT:
case CloudSimTags.INFOPKT_RETURN:
this.tag = tag;
flag = true;
break;
default:
flag = false;
break;
}
return flag;
}
/**
* Sets the destination ID for this packet.
*
* @param id this packet's destination ID
*
* @pre id > 0
* @post $none
*/
public void setDestId(int id) {
this.destId = id;
}
}