Commit 35ea93a4 authored by Simon Luser's avatar Simon Luser
Browse files

Merge remote-tracking branch 'origin/master' into pl/disasterPrioritization

parents 92774550 6c429d62
package de.tud.kom.p2psim.impl.topology.movement.modularosm.movementIconVisualisation;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
/**
* Interface for the state selector which shall be used in conjunction with the
* {@link ModularMovementIconVis} in order to use state icons.
*
* @author Clemens Krug
*/
public interface StateSelector
{
/**
* Returns the state of the host as string. The returned state
* must be equal to the one specified in the state-icon mapping to have any effect.
* The state of a host can not be null! In case there is no state matched which has an icon
* specified, you can return whatever string you like.
*
* @param ms The host of whom the state should be determined.
* @return The state of the host as string, not null.
*/
String getState(SimLocationActuator ms);
}
package de.tud.kom.p2psim.impl.topology.movement.modularosm.transition;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.AttractionPoint;
import java.util.*;
/**
* This {@link ITransitionStrategy} works with manual assignments. Initially components will be assigned
* one of the attraction points, but at any further point, the set list of attraction points doesn't really matter.
* New target can be assigned by using the {@link #updateTargetAttractionPoint(SimLocationActuator, AttractionPoint)} method,
* otherwise the components will stop moving upon reaching their target.
*
* @author Clemens Krug
*/
public class ManualAssignmentStrategy implements ITransitionStrategy
{
private LinkedHashSet<AttractionPoint> aPoints = new LinkedHashSet<>();
private Map<SimLocationActuator, AttractionPoint> assignments = new HashMap<>();
private List<AttractionAssignmentListener> listeners = new LinkedList<>();
@Override
public AttractionPoint getAssignment(SimLocationActuator comp)
{
return assignments.get(comp);
}
@Override
public void addAttractionAssignmentListener(AttractionAssignmentListener listener)
{
listeners.add(listener);
}
@Override
public void removeAttractionAssignmentListener(AttractionAssignmentListener listener)
{
listeners.remove(listener);
}
@Override
public void setAttractionPoints(Collection<AttractionPoint> attractionPoints) {
aPoints.addAll(attractionPoints);
}
@Override
public Set<AttractionPoint> getAllAttractionPoints() {
return aPoints;
}
@Override
public void addComponent(SimLocationActuator ms) {
if(!assignments.containsKey(ms))
{
AttractionPoint aPoint = aPoints.iterator().next();
assignments.put(ms, aPoint);
}
listeners.forEach(listener -> listener.updatedAttractionAssignment(ms, assignments.get(ms)));
}
@Override
public void reachedAttractionPoint(SimLocationActuator ms) {
//Nothing to do.
}
@Override
public void updateTargetAttractionPoint(SimLocationActuator comp, AttractionPoint attractionPoint) {
assignments.put(comp, attractionPoint);
listeners.forEach(listener -> listener.updatedAttractionAssignment(comp, attractionPoint));
}
}
package de.tud.kom.p2psim.impl.topology.movement.modularosm.transition;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import de.tud.kom.p2psim.api.topology.Topology;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.BasicAttractionPoint;
import de.tudarmstadt.maki.simonstrator.api.Binder;
import de.tudarmstadt.maki.simonstrator.api.Monitor;
import de.tudarmstadt.maki.simonstrator.api.Randoms;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.AttractionPoint;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
/**
* This {@link ITransitionStrategy} makes clients move around randomly in a specified area. You can specify the target
* area center via the {@link #updateTargetAttractionPoint(SimLocationActuator, AttractionPoint)} method. The client will then start
* to roam the area randomly till a new target area is assigned.
*
* @author Clemens Krug
*/
public class RandomInAreaTransitionStrategy implements ITransitionStrategy
{
private final Random random = Randoms
.getRandom(RandomInAreaTransitionStrategy.class);
private LinkedHashSet<AttractionPoint> aPoints = new LinkedHashSet<>();
/**
* These are the target area centers the clients have assigned.
*/
private Map<SimLocationActuator, AttractionPoint> assignments = new HashMap<>();
/**
* These are the current spots inside the target area where the client is currently heading.
*/
private Map<SimLocationActuator, AttractionPoint> currentTarget = new HashMap<>();
private Map<SimLocationActuator, Integer> currentSearchRadius = new HashMap<>();
private List<AttractionAssignmentListener> listeners = new LinkedList<>();
/**
* The radius the target area should have. Should be set via XML config file.
*/
private int defaultRadius;
@Override
public AttractionPoint getAssignment(SimLocationActuator comp)
{
return currentTarget.get(comp);
}
@Override
public void addAttractionAssignmentListener(AttractionAssignmentListener listener)
{
listeners.add(listener);
}
@Override
public void removeAttractionAssignmentListener(AttractionAssignmentListener listener)
{
listeners.remove(listener);
}
@Override
public void setAttractionPoints(Collection<AttractionPoint> attractionPoints) {
aPoints.addAll(attractionPoints);
}
@Override
public Set<AttractionPoint> getAllAttractionPoints() {
return aPoints;
}
@Override
public void addComponent(SimLocationActuator ms) {
if(!assignments.containsKey(ms))
{
AttractionPoint aPoint = aPoints.iterator().next();
assignments.put(ms, aPoint);
currentTarget.put(ms, nextRandomPosition(aPoint, defaultRadius));
currentSearchRadius.put(ms, defaultRadius);
}
listeners.forEach(listener -> listener.updatedAttractionAssignment(ms, currentTarget.get(ms)));
}
@Override
public void reachedAttractionPoint(SimLocationActuator ms) {
currentTarget.put(ms, nextRandomPosition(assignments.get(ms), currentSearchRadius.get(ms)));
listeners.forEach(listener -> listener.updatedAttractionAssignment(ms, currentTarget.get(ms)));
}
@Override
public void updateTargetAttractionPoint(SimLocationActuator comp, AttractionPoint attractionPoint) {
assignments.put(comp, attractionPoint);
currentTarget.put(comp, nextRandomPosition(attractionPoint, currentSearchRadius.get(comp)));
listeners.forEach(listener -> listener.updatedAttractionAssignment(comp, attractionPoint));
}
public void setSearchRadiusForComponent(SimLocationActuator ms, int radius)
{
currentSearchRadius.put(ms, radius);
}
public void setDefaultRadius(int radius)
{
this.defaultRadius = radius;
}
/**
* Calculates a random point within a given circular area.
* @param center The center of the area.
* @param radius The radius of the area.
* @return A random position within the area.
*/
private BasicAttractionPoint nextRandomPosition(Location center, int radius)
{
assert radius > 0 : "An area radius must be specified for the RandomInAreaTransitionStrategy! Did you set the 'DefaultRadius' property for this transition?";
double x = center.getLongitude();
double y = center.getLatitude();
double newX = -1;
double newY = -1;
int tries = 0;
while(newX < 0.0 || newX > Binder.getComponentOrNull(Topology.class).getWorldDimensions().getX()
|| newY < 0.0 || newY > Binder.getComponentOrNull(Topology.class).getWorldDimensions().getY())
{
double calcRadius = random.nextDouble() * radius;
double calcAngle = random.nextDouble() * 360;
newX = x + Math.sin(calcAngle) * calcRadius;
newY = y + Math.cos(calcAngle) * calcRadius;
tries++;
if(tries > 100) throw new AssertionError("Unable to find a valid target destination within <100 tries.");
}
Monitor.log(this.getClass(), Monitor.Level.DEBUG, "Next random position is " + newX + " / " + newY);
return new BasicAttractionPoint("RNDPOS", new PositionVector(newX, newY));
}
}
...@@ -110,8 +110,8 @@ public class CsvPlacement implements PlacementModel { ...@@ -110,8 +110,8 @@ public class CsvPlacement implements PlacementModel {
if (XY.getX() > world.getX() || XY.getY() > world.getY() || XY.getX() < 0 if (XY.getX() > world.getX() || XY.getY() > world.getY() || XY.getX() < 0
|| XY.getY() < 0) { || XY.getY() < 0) {
// System.err.println("Skipped entry " + x + ";" // System.err.println("Skipped entry " + x + ";"
// + y); // + y);
continue; continue;
} }
......
...@@ -30,7 +30,6 @@ import de.tud.kom.p2psim.api.linklayer.mac.Link; ...@@ -30,7 +30,6 @@ import de.tud.kom.p2psim.api.linklayer.mac.Link;
import de.tud.kom.p2psim.api.linklayer.mac.MacAddress; import de.tud.kom.p2psim.api.linklayer.mac.MacAddress;
import de.tud.kom.p2psim.api.linklayer.mac.MacLayer; import de.tud.kom.p2psim.api.linklayer.mac.MacLayer;
import de.tud.kom.p2psim.api.linklayer.mac.PhyType; import de.tud.kom.p2psim.api.linklayer.mac.PhyType;
import de.tud.kom.p2psim.api.topology.movement.MovementSupported;
import de.tud.kom.p2psim.api.topology.obstacles.ObstacleModel; import de.tud.kom.p2psim.api.topology.obstacles.ObstacleModel;
import de.tud.kom.p2psim.api.topology.waypoints.WaypointModel; import de.tud.kom.p2psim.api.topology.waypoints.WaypointModel;
import de.tud.kom.p2psim.impl.topology.PositionVector; import de.tud.kom.p2psim.impl.topology.PositionVector;
...@@ -529,8 +528,9 @@ public class FiveGTopologyView extends AbstractTopologyView<CellLink> { ...@@ -529,8 +528,9 @@ public class FiveGTopologyView extends AbstractTopologyView<CellLink> {
public long getBandwidth(boolean isBroadcast) { public long getBandwidth(boolean isBroadcast) {
assert (apLinkData != null && supportsAccessPoints) assert (apLinkData != null && supportsAccessPoints)
|| apLinkData == null; || apLinkData == null;
return apLinkData != null ? apLinkData.getBandwidth(isUpload) long tmp = apLinkData != null ? apLinkData.getBandwidth(isUpload)
: linkData.getBandwidth(isUpload); : linkData.getBandwidth(isUpload);
return tmp;
} }
@Override @Override
...@@ -628,4 +628,4 @@ public class FiveGTopologyView extends AbstractTopologyView<CellLink> { ...@@ -628,4 +628,4 @@ public class FiveGTopologyView extends AbstractTopologyView<CellLink> {
} }
} }
\ No newline at end of file
...@@ -801,10 +801,29 @@ public class VisualizationTopologyView extends JFrame ...@@ -801,10 +801,29 @@ public class VisualizationTopologyView extends JFrame
SCALE = scale; SCALE = scale;
} }
/**
* Returns the SCALED value of the given value. This is to be used by
* visualizations!
*
* @param value
* @return
*/
public static int scaleValue(double value) { public static int scaleValue(double value) {
return (int) (value * getScale()); return (int) (value * getScale());
} }
/**
* Returns the original value (in meters) of the given scaled value.
* This should be used if you need map values in meters from a scaled
* value. E.g. to find segments in a to meters mapped vector.
*
* @param value
* @return
*/
public static double originalValue(int value) {
return value * (1 / getScale());
}
/** /**
* Recommended way to add a custom visualization layer. * Recommended way to add a custom visualization layer.
* *
......
/*
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
*
* This file is part of PeerfactSim.KOM.
*
* PeerfactSim.KOM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>.
*
*/
package de.tud.kom.p2psim.impl.topology.views.fiveg;
import java.util.HashMap;
import java.util.HashSet;
import de.tud.kom.p2psim.api.linklayer.mac.MacAddress;
import de.tud.kom.p2psim.api.scenario.ConfigurationException;
import de.tud.kom.p2psim.impl.topology.views.VisualizationTopologyView.VisualizationInjector;
import de.tud.kom.p2psim.impl.topology.views.fiveg.models.AbstractModel;
import de.tud.kom.p2psim.impl.topology.views.fiveg.utils.Direction;
import de.tud.kom.p2psim.impl.topology.views.fiveg.utils.ParameterType;
import de.tud.kom.p2psim.impl.topology.views.visualization.world.ModelFiveGVisualization;
import de.tudarmstadt.maki.simonstrator.api.Event;
import de.tudarmstadt.maki.simonstrator.api.EventHandler;
import de.tudarmstadt.maki.simonstrator.api.Time;
/**
* A grid based FiveG model-based database.
*
* This module allows to add transmission models to each segment of the map to
* accommodate different behaviors of wireless network transmission
* technologies. It enables the developer to define different models for
* **Latency**, **Bandwidth** and **Drop Rate** (called *characteristics*), for
* **Upload** and **Download** and for every **Segment**.
*
* For more information see README.md in
* de.tud.kom.p2psim.impl.topology.views.fiveg.models.README.md
*
* @author Nils Richerzhagen
* @version 1.0, Jul 7, 2017
*/
public class ModelBasedSegmentDatabase
extends AbstractGridBasedTopologyDatabase {
final Integer DEFAULT_SEGMENT_ID = new Integer(-1);
// Models[Type][SegID][Up/Down/Both]
HashMap<ParameterType, HashMap<Integer, HashMap<Direction, AbstractModel>>> models = new HashMap<>();
public ModelBasedSegmentDatabase() {
super(100, true);
super.setSupportCloudlets(true);
}
@Override
protected Entry createEntryFor(int segmentID, boolean isCloudlet) {
return new ModelBasedEntry(segmentID);
}
@Override
public void setEnableVis(boolean enableVis) {
if (enableVis == true) {
Event.scheduleImmediately(new EventHandler() {
@Override
public void eventOccurred(Object content, int type) {
ModelFiveGVisualization viz = ModelFiveGVisualization.getInstance();
viz.setDatabase(ModelBasedSegmentDatabase.this);
VisualizationInjector.injectComponent(viz);
}
}, null, 0);
}
}
/**
* Add a model to Database
*
* @param model
* the model to add
*/
public void setModel(AbstractModel model) {
// Enable debugging
model.debug();
// Check if model is valid
ParameterType type = model.getParameterType();
if (type == null) {
throw new ConfigurationException(
"Model is not defined for any Parameter Type. Please specify the Type for this Model.");
}
Direction dir = model.getDirection();
if (dir == null) {
throw new ConfigurationException(
"Model is not defined for any Direction. Please specify the Direction for this Model.");
}
Integer segmentID = new Integer(model.getSegmentID());
// Check if there is no contradicting model
if (models.containsKey(type)) {
// There is already this Type
if (models.get(type).containsKey(segmentID)) {
// There is already this SegID
if (models.get(type).get(segmentID).containsKey(dir)
|| (models.get(type).get(segmentID)
.containsKey(Direction.BOTH)
&& (dir.equals(Direction.DOWNLOAD)
|| dir.equals(Direction.UPLOAD)))
|| (dir.equals(Direction.BOTH) && (models.get(type)
.get(segmentID).containsKey(Direction.DOWNLOAD)
|| models.get(type).get(segmentID)
.containsKey(Direction.UPLOAD)))) {
// There is already a model defined
throw new ConfigurationException(
"Conflicting Models for SegmentID " + segmentID
+ ", Type " + type.toString()
+ " and Direction " + dir.toString());
} else {
// Add new model
models.get(type).get(segmentID).put(dir, model);
}
} else {
// Add new SegmentID
// Direction => Model
HashMap<Direction, AbstractModel> tmp1 = new HashMap<>();
tmp1.put(dir, model);
models.get(type).put(segmentID, tmp1);
}
} else {
// Add new model
// Direction => Model
HashMap<Direction, AbstractModel> tmp1 = new HashMap<>();
tmp1.put(dir, model);
// SegID => [Direction => Model]
HashMap<Integer, HashMap<Direction, AbstractModel>> tmp2 = new HashMap<>();
tmp2.put(segmentID, tmp1);
models.put(type, tmp2);
}
}
/**
* Get the model for the specific combination
*
* @param segID
* The SegmentID to get the model for
* @param type
* The Type of the Parameter
* @param isUpload
* Is it a Up or Downlink
* @return The Model for the given segment
*/
AbstractModel getModel(int segID, ParameterType type, Boolean isUpload) {
Integer segmentID = new Integer(segID);
Direction dir = Direction.DOWNLOAD;
if (isUpload) {
dir = Direction.UPLOAD;
}
// Check if type exists
if (!this.models.containsKey(type)) {
throw new ConfigurationException(
"No Model is defined for " + type + ".");
}
// Check if there is a specific model
if(this.models.get(type).containsKey(segmentID) && this.models.get(type).get(segmentID).containsKey(dir)) {
return this.models.get(type).get(segmentID).get(dir);
}
// Check if there is a BOTH model in this segment
if(this.models.get(type).containsKey(segmentID) && this.models.get(type).get(segmentID).containsKey(Direction.BOTH)) {
return this.models.get(type).get(segmentID).get(Direction.BOTH);
}
// Check default model for specific model
if(this.models.get(type).containsKey(DEFAULT_SEGMENT_ID) && this.models.get(type).get(DEFAULT_SEGMENT_ID).containsKey(dir)) {
return this.models.get(type).get(DEFAULT_SEGMENT_ID).get(dir);
}
// Check if there is a default BOTH model
if(this.models.get(type).containsKey(DEFAULT_SEGMENT_ID) && this.models.get(type).get(DEFAULT_SEGMENT_ID).containsKey(Direction.BOTH)) {
return this.models.get(type).get(DEFAULT_SEGMENT_ID).get(Direction.BOTH);
}
throw new ConfigurationException(
"No Model is defined for Type " + type + ", Segment ID "
+ segmentID + " and Direction " + dir + ".");
}
public class ModelBasedEntry implements FiveGTopologyDatabase.Entry {
// How is a overload defined
// FIXME Can the time in the Latency result in problems if the drop-rate is set to 100%?
private final long OVERLOAD_LATENCY = 9999 * Time.MILLISECOND;
private final long OVERLOAD_BANDWIDTH = 1;
private final double OVERLOAD_DROPRATE = 1;
// When is a node considered overloaded
private final long THRESHOLD_LATENCY = Time.SECOND;
private final long THRESHOLD_BANDWIDTH = 10;
private final double THRESHOLD_DROPRATE = 1;
private final double YELLOW_INDICATOR = .8;
// Other storage
private final int segment;
private boolean isAvailable = true;
private HashSet<MacAddress> hostsInSegment = new HashSet<>();
private boolean overload;
// The current metrics of this segment
private long bandUp;
private long bandDown;
private long latUp;
private long latDown;
private double dropUp;
private double dropDown;
/**
* Create a new entry for the given segment
*
* @param segment
*/
public ModelBasedEntry(int segment) {
this.segment = segment;
calc();
}
@Override
public int getSegmentID() {
return segment;
}
/**
* A host leaves this segment
*/
public void onHostLeavesSegment(MacAddress hostAddr) {
// Remove MAC from current users
this.hostsInSegment.remove(hostAddr);
calc();
}
/**
* A host enters this segment
*/
public void onHostEntersSegment(MacAddress hostAddr) {
// Add MAC to current users
this.hostsInSegment.add(hostAddr);
calc();
}
@Override
public double getDropProbability(boolean isUpload) {
// Segment is overloaded or not available return overloaded drop
// probability
if (!isAvailable || overload) {
return OVERLOAD_DROPRATE;
}
// Return calculated drop probability
if (isUpload) {
return dropUp;
} else {
return dropDown;
}
}
@Override
public long getLatency(boolean isUpload) {
// Segment is overloaded or not available return overloaded latency
if (!isAvailable || overload) {
return OVERLOAD_LATENCY;
}
// Return calculated latency
if (isUpload) {
return latUp;
} else {
return latDown;
}
}
@Override
public long getBandwidth(boolean isUpload) {
// Segment is overloaded or not available return overloaded
// bandwidth
if (!isAvailable || overload) {
return OVERLOAD_BANDWIDTH;
}
// Return calculated bandwidth
if (isUpload) {
return bandUp;
} else {
return bandDown;
}
}
@Override
public boolean isAvailable() {
return isAvailable;
}
@Override
public void setAvailability(boolean isAvailable) {
this.isAvailable = isAvailable;
}
public int getStatus(ParameterType type, Direction dir) {
if(type.equals(ParameterType.BANDWIDTH) && dir.equals(Direction.UPLOAD)) {
if(this.bandUp <= THRESHOLD_BANDWIDTH) {
return 2;
}
if(this.bandUp < ((2 - YELLOW_INDICATOR) * THRESHOLD_BANDWIDTH)) {
return 1;
}
return 0;
}
if(type.equals(ParameterType.BANDWIDTH) && dir.equals(Direction.DOWNLOAD)) {
if(this.bandDown <= THRESHOLD_BANDWIDTH) {
return 2;
}
if(this.bandDown < ((2 - YELLOW_INDICATOR) * THRESHOLD_BANDWIDTH)) {
return 1;
}
return 0;
}
if(type.equals(ParameterType.DROPRATE) && dir.equals(Direction.UPLOAD)) {
if(this.dropUp >= THRESHOLD_DROPRATE) {
return 2;
}
if(this.dropUp > (YELLOW_INDICATOR * THRESHOLD_DROPRATE)) {
return 1;
}
return 0;
}
if(type.equals(ParameterType.DROPRATE) && dir.equals(Direction.DOWNLOAD)) {
if(this.dropDown >= THRESHOLD_DROPRATE) {
return 2;
}
if(this.dropDown > (YELLOW_INDICATOR * THRESHOLD_DROPRATE)) {
return 1;
}
return 0;
}
if(type.equals(ParameterType.LATENCY) && dir.equals(Direction.UPLOAD)) {
if(this.latUp >= THRESHOLD_LATENCY) {
return 2;
}
if(this.latUp > ((2 - YELLOW_INDICATOR) * THRESHOLD_LATENCY)) {
return 1;
}
return 0;
}
if(type.equals(ParameterType.LATENCY) && dir.equals(Direction.DOWNLOAD)) {
if(this.latDown >= THRESHOLD_LATENCY) {
return 2;
}
if(this.latDown > ((2 - YELLOW_INDICATOR) * THRESHOLD_LATENCY)) {
return 1;
}
return 0;
}
return 0;
}
public boolean isOverloaded() {
return overload;
}
public int getHostsInSegment() {
return this.hostsInSegment.size();
}
/**
* Recalculate every metric when a host leaves or enters
*/
private void calc() {
int users = this.hostsInSegment.size();
// Assume not overloaded
this.overload = false;
// Calc Bandwidth
this.bandUp = getModel(getSegmentID(), ParameterType.BANDWIDTH,
true).getLong(users);
this.bandDown = getModel(getSegmentID(), ParameterType.BANDWIDTH,
false).getLong(users);
if (bandDown <= THRESHOLD_BANDWIDTH
|| bandUp <= THRESHOLD_BANDWIDTH) {
overload = true;
}
// Calc Latency
this.latUp = getModel(getSegmentID(), ParameterType.LATENCY, true)
.getLong(users);
this.latDown = getModel(getSegmentID(), ParameterType.LATENCY,
false).getLong(users);
if (latUp >= THRESHOLD_LATENCY || latDown >= THRESHOLD_LATENCY) {
overload = true;
}
// Calc Droprate
this.dropUp = getModel(getSegmentID(), ParameterType.DROPRATE, true)
.getDouble(users);
this.dropDown = getModel(getSegmentID(), ParameterType.DROPRATE,
false).getDouble(users);
if (dropUp >= THRESHOLD_DROPRATE
|| dropDown >= THRESHOLD_DROPRATE) {
overload = true;
}
}
}
}
/*
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
*
* This file is part of PeerfactSim.KOM.
*
* PeerfactSim.KOM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>.
*
*/
package de.tud.kom.p2psim.impl.topology.views.fiveg.models;
import de.tud.kom.p2psim.api.scenario.ConfigurationException;
import de.tud.kom.p2psim.impl.topology.views.FiveGTopologyView;
import de.tud.kom.p2psim.impl.topology.views.fiveg.ModelBasedSegmentDatabase;
import de.tud.kom.p2psim.impl.topology.views.fiveg.utils.Direction;
import de.tud.kom.p2psim.impl.topology.views.fiveg.utils.Graph;
import de.tud.kom.p2psim.impl.topology.views.fiveg.utils.ParameterType;
/**
* Abstract base model for the {@link FiveGTopologyView} when using the {@link ModelBasedSegmentDatabase}.
*
* @author Nils
* @version 1.0, 05.03.2017
*/
public abstract class AbstractModel {
// Storage
private int segmentID = -1;
private ParameterType type;
private Direction dir = Direction.BOTH;
// Is debug enabled for this model
private boolean debug = false;
public void setSegmentID(int segmentid) {
assert segmentid > 0;
this.segmentID = segmentid;
}
public int getSegmentID() {
return this.segmentID;
}
/**
* Set the parameter type {@link ParameterType}
* @param param
*/
public void setParameterType(String param) {
param = param.toUpperCase();
// Check if type is valid
try {
this.type = ParameterType.valueOf(param);
} catch (IllegalArgumentException e) {
throw new ConfigurationException(
"The Parameter " + param + " is unknown. Please select one of "
+ ParameterType.printTypes());
}
if(this.type == null) {
throw new ConfigurationException(
"The Parameter " + param + " is unknown. Please select one of "
+ ParameterType.printTypes());
}
}
public ParameterType getParameterType() {
return type;
}
/**
* Set the direction of model {@link Direction}
* @param param
*/
public void setDirection(String param) {
param = param.toUpperCase();
try {
this.dir = Direction.valueOf(param);
} catch (IllegalArgumentException e) {
throw new ConfigurationException(
"Direction " + param + " is unknown. Please select one of "
+ Direction.printTypes());
}
if(this.type == null) {
throw new ConfigurationException(
"Direction " + param + " is unknown. Please select one of "
+ Direction.printTypes());
}
}
public Direction getDirection() {
return dir;
}
/**
* Enable debugging - visualization of the model set in the config.
*
* @param debug
*/
public void setDebug(boolean debug) {
this.debug = debug;
}
public boolean getDebug() {
return this.debug;
}
public abstract long getLong(int users);
public abstract double getDouble(int users);
/**
* Debug this model
*/
public void debug() {
Graph test = new Graph();
test.setModel(this);
}
}
/*
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
*
* This file is part of PeerfactSim.KOM.
*
* PeerfactSim.KOM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>.
*
*/
package de.tud.kom.p2psim.impl.topology.views.fiveg.models;
/**
* A Constant Model which return always the constant value C
* c(u) = C
* @author Marc Schiller
* @version 1.0, 15 Dec 2016
*/
public class ConstantModel extends AbstractModel {
private double c = 0;
public void setC(double c) {
this.c = c;
}
@Override
public long getLong(int users) {
return (long) this.c;
}
@Override
public double getDouble(int users) {
return this.c;
}
public String toString() {
return "Constant Model: c(u) = " + c;
}
}
/*
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
*
* This file is part of PeerfactSim.KOM.
*
* PeerfactSim.KOM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>.
*
*/
package de.tud.kom.p2psim.impl.topology.views.fiveg.models;
/**
* A cut off model based on the heaviside step function.
*
* https://de.wikipedia.org/wiki/Heaviside-Funktion
*
* cut(u) = a * θ(c * u + d) + b
* @author Marc Schiller
* @version 1.0, 15 Dec 2016
*/
public class CutOffModel extends AbstractModel {
private double a = 1;
private double b = 0;
private double c = 1;
private double d = 0;
public void setA(double a) {
this.a = a;
}
public void setB(double b) {
this.b = b;
}
public void setC(double c) {
this.c = c;
}
public void setD(double d) {
this.d = d;
}
private double heaviside(double x) {
if(x < 0) {
return 0;
} else {
return 1;
}
}
@Override
public long getLong(int users) {
return (long) getDouble(users);
}
@Override
public double getDouble(int users) {
return this.a * heaviside(this.c * users + this.d) + this.b;
}
@Override
public String toString() {
return "CutOffModel: cut(u) = " + this.a + " * θ(" + this.c + " * u + " + this.d + ") + " + this.b;
}
}
/*
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
*
* This file is part of PeerfactSim.KOM.
*
* PeerfactSim.KOM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>.
*
*/
package de.tud.kom.p2psim.impl.topology.views.fiveg.models;
/**
* An exponential model
* exp(u) = a * e^(c * (u - d)) + b
* @author Marc Schiller
* @version 1.0, 15 Dec 2016
*/
public class ExponentialModel extends AbstractModel {
// exp(u) = a * e ^(c * u + d) + b
private double a = 1;
private double b = 0;
private double c = 1;
private double d = 0;
public void setA(double a) {
this.a = a;
}
public void setB(double b) {
this.b = b;
}
public void setC(double c) {
this.c = c;
}
public void setD(double d) {
this.d = d;
}
@Override
public long getLong(int users) {
return (long) getDouble(users);
}
@Override
public double getDouble(int users) {
return this.a * Math.exp(this.c * (users - this.d)) + this.b;
}
@Override
public String toString() {
return "Exponential Model: exp(u) = " + this.a + " * e^(" + this.c + " * (u - " + this.d + ")) + " + this.b;
}
}
/*
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
*
* This file is part of PeerfactSim.KOM.
*
* PeerfactSim.KOM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>.
*
*/
package de.tud.kom.p2psim.impl.topology.views.fiveg.models;
/**
* Linear Model
* lin(u) = a * u + b
* @author Marc Schiller
* @version 1.0, 15 Dec 2016
*/
public class LinearModel extends AbstractModel {
private double a = 1;
private double b = 0;
public void setA(double a) {
this.a = a;
}
public void setB(double b) {
this.b = b;
}
@Override
public long getLong(int users) {
return (long) (this.a * users + this.b);
}
@Override
public double getDouble(int users) {
return this.a * users + this.b;
}
public String toString() {
return "Linear Model: lin(u) = " + a + " * u + " + b;
}
}
/*
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
*
* This file is part of PeerfactSim.KOM.
*
* PeerfactSim.KOM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>.
*
*/
package de.tud.kom.p2psim.impl.topology.views.fiveg.models;
/**
* Logarithmic model
* log(u) = a * ln(c * (u - d)) + b
* @author Marc Schiller
* @version 1.0, 15 Dec 2016
*/
public class LogarithmicModel extends AbstractModel {
private double a = 1;
private double b = 0;
private double c = 1;
private double d = 0;
public void setA(double a) {
this.a = a;
}
public void setB(double b) {
this.b = b;
}
public void setC(double c) {
this.c = c;
}
public void setD(double d) {
this.d = d;
}
@Override
public long getLong(int users) {
return (long) getDouble(users);
}
@Override
public double getDouble(int users) {
double tmp = this.a * Math.log(this.c * (users - this.d)) + this.b;
if(tmp < 0) {
return 0;
} else {
return tmp;
}
}
@Override
public String toString() {
return "Logarithmic Model: log(u) = " + this.a + " * ln(" + this.c + " * (u - " + this.d + ")) + " + this.b;
}
}
# 5G Models
> **IMPORTANT!** The colors of each segment reflect the status *per* characteristic not the global status of this segment. If a segment is overloaded the text "overload" is shown.
This module allows to add transmission models to each segment of the map to accommodate different behaviors of wireless network transmission technologies. It enables the developer to define different models for **Latency**, **Bandwidth** and **Drop Rate** (called *characteristics*), for **Upload** and **Download** and for every **Segment**.
Whenever one of the characteristic for a client is requested every other characteristic is evaluated to check if one of them is overloaded such that no connection is possible. The thresholds for the overload are defined in [`FiveGTopologyDatabase.Entry`](https://dev.kom.e-technik.tu-darmstadt.de/gitlab/simonstrator/simonstrator-peerfactsim/blob/nr/monitoring-model/src/de/tud/kom/p2psim/impl/topology/views/fiveg/ModelBasedSegmentDatabase.java#L182)
## Configuration / Setup
The models are enabled by changing the `Database` of the `FiveGTopologyView` to `ModelBasedSegmentDatabase`. For a minimal config the `ModelBasedSegmentDatabase` needs at least a model for each characteristic. Therefore, the models are passed to the database. Each model has its specific defaults described [here](#models). In addition to that every model has parameters for `direction` (*UPLOAD*, *DOWNLOAD* or **BOTH**), `parameterType` (*BANDWIDTH*, *LATENCY* and *DROPRATE*), `segmentID` (to which segmentID this model is applied - **-1** means that it is applied to every segment) and debug (TRUE or **FALSE**). **Bold** values mark the defaults.
## Examples
> **IMPORTANT!** For every characteristic there needs to be one and *only one* default model.
### General Setup
Here the general setup for the model based segments is shown. The models are placed inside the database element.
```xml
<View class="de.tud.kom.p2psim.impl.topology.views.FiveGTopologyView" phy="UMTS" cloudGroups="Cloud">
<Database class="de.tud.kom.p2psim.impl.topology.views.fiveg.ModelBasedSegmentDatabase" enableVis="$ENABLE_VIS" gridSize="$CELL_GRID_SIZE">
<!-- Place model definitions here -->
</Database>
</View>
```
### A default constant model for every characteristic
```xml
<Model class="de.tud.kom.p2psim.impl.topology.views.fiveg.models.ConstantModel" c="300" parameterType="BANDWIDTH" />
<Model class="de.tud.kom.p2psim.impl.topology.views.fiveg.models.ConstantModel" c="5" parameterType="LATENCY" />
<Model class="de.tud.kom.p2psim.impl.topology.views.fiveg.models.ConstantModel" c="0.1" parameterType="DROPRATE" />
```
For every segment the bandwidth is 300 kBit/s, the latency 5 ms and drop rate is 1% (0.1) in both directions.
### Advanced setup
```xml
<Model class="de.tud.kom.p2psim.impl.topology.views.fiveg.models.ConstantModel" c="300" parameterType="BANDWIDTH" direction="UPLOAD" />
<Model class="de.tud.kom.p2psim.impl.topology.views.fiveg.models.ConstantModel" c="10" parameterType="BANDWIDTH" direction="DOWNLOAD" />
<Model class="de.tud.kom.p2psim.impl.topology.views.fiveg.models.LogarithmicModel" a="3" b="10" c="-5" d="-10" parameterType="LATENCY" />
<Model class="de.tud.kom.p2psim.impl.topology.views.fiveg.models.ExponentialModel" parameterType="DROPRATE" />
<Model class="de.tud.kom.p2psim.impl.topology.views.fiveg.models.CutoffModel" parameterType="BANDWIDTH" segmentID="123" debug="TRUE" />
```
Every segment has 300 kBit/s upload bandwidth and 10 kBit/s download bandwidth with a constant model. The latency of every segment is equal for up- and download and is based on a logarithmic model with $`a=3`$, $`b=10`$, $`c=-5`$ and $`d=-10`$. A default exponential model is applied on the latency. At last there is a cut-off model for the bandwidth for the segment with the ID `123`. It also shows the debug graph.
## Models
* [Constant](#constant)
* [Linear](#linear)
* [Exponential](#exponential)
* [Logarithmic](#logarithmic)
* [Cut-Off](#cut-off)
### Constant
![](https://dev.kom.e-technik.tu-darmstadt.de/gitlab/simonstrator/simonstrator-peerfactsim/raw/nr/monitoring-model/src/de/tud/kom/p2psim/impl/topology/views/fiveg/models/img/constant.png)
$`c(u)=C`$
> The constant model applies the the same constant value `c` to the selected characteristic regardless of the number of hosts in the segment.
*Model-specific Parameters*:
`c` the constant value (*default* `0`)
### Linear
![](https://dev.kom.e-technik.tu-darmstadt.de/gitlab/simonstrator/simonstrator-peerfactsim/raw/nr/monitoring-model/src/de/tud/kom/p2psim/impl/topology/views/fiveg/models/img/linear.png)
$`lin(u)=a*u+b`$
*Model-specific Parameters*:
`a` the slope (*default* `1`)
`b` y-axis intersection (*default* `0`)
### Exponential
![](https://dev.kom.e-technik.tu-darmstadt.de/gitlab/simonstrator/simonstrator-peerfactsim/raw/nr/monitoring-model/src/de/tud/kom/p2psim/impl/topology/views/fiveg/models/img/exponential.png)
$`exp(u)=a*e^{c(u-d)}+b`$
*Model-specific Parameters*:
`a` scaling factor (*default* `1`)
`b` y-axis offset (*default* `0`)
`c` exponent scaling (*default* `1`)
`d` x-axis offset (*default* `0`)
### Logarithmic
![](https://dev.kom.e-technik.tu-darmstadt.de/gitlab/simonstrator/simonstrator-peerfactsim/raw/nr/monitoring-model/src/de/tud/kom/p2psim/impl/topology/views/fiveg/models/img/logarithmic.png)
$`log(u)=a*ln(c(u-d))+b`$
*Model-specific Parameters*:
`a` scaling factor (*default* `1`)
`b` y-axis offset (*default* `0`)
`c` logarithm scaling (*default* `1`)
`d` x-axis offset (*default* `0`)
### Cut-Off
![](https://dev.kom.e-technik.tu-darmstadt.de/gitlab/simonstrator/simonstrator-peerfactsim/raw/nr/monitoring-model/src/de/tud/kom/p2psim/impl/topology/views/fiveg/models/img/cutoff.png)
$`cut(u)=a*\theta(c(u-d))+b`$
> The cut-off model is based on the [Heaviside step function](https://en.wikipedia.org/wiki/Heaviside_step_function).
*Model-specific Parameters*:
`a` scaling factor (*default* `1`)
`b` y-axis offset (*default* `0`)
`c` scaling (*default* `1`)
`d` x-axis offset (*default* `0`)
\ No newline at end of file
/*
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
*
* This file is part of PeerfactSim.KOM.
*
* PeerfactSim.KOM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>.
*
*/
package de.tud.kom.p2psim.impl.topology.views.fiveg.utils;
/**
* Enumeration for defining the direction (Up,Down or Both) for a model.
* @author Marc Schiller
* @version 1.0, 15 Dec 2016
*/
public enum Direction {
BOTH(),
UPLOAD(),
DOWNLOAD();
public static String printTypes() {
Direction[] types = values();
String out = "";
for (int i = 0; i < types.length; i++) {
if (i > 0) {
out += ", ";
}
out += types[i].name();
}
return out;
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment