Commit db566de9 authored by Björn Richerzhagen's avatar Björn Richerzhagen
Browse files

5G Topology-View

- for scenarios with mobile users and clouds/cloudlets
- assigns link latency/drop/bw based on the clients position and whether
he/she is talking to a cloud or a cloudlet
- based on measured data
- added a corresponding visualization
parent 71a2596c
/*
* 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;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import de.tud.kom.p2psim.api.common.HostProperties;
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.MacLayer;
import de.tud.kom.p2psim.api.linklayer.mac.PhyType;
import de.tud.kom.p2psim.api.topology.obstacles.ObstacleModel;
import de.tud.kom.p2psim.api.topology.waypoints.WaypointModel;
import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.views.FiveGTopologyView.CellLink;
import de.tud.kom.p2psim.impl.topology.views.fiveg.FiveGTopologyDatabase;
import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
import edu.emory.mathcs.backport.java.util.Arrays;
/**
* This topology view offers a topology for mobile apps - mobile clients
* maintain one to one connections to one or multiple cloud servers or cloudlet
* instances. This view abstracts from real antennas in that the actual range of
* an antenna etc. is just modeled as a property of the link between mobile
* client and the endpoint (cloud/cloudlet) based on a client's position. This
* way, measurements such as the ones by Kaup et al. can be easily incorporated.
*
* TODO add a property to enable usage of access points (lower latency, higher
* BW at certain client positions around the configured positions of APs)
* <code><Properties canUseAccessPoints="true" /></code>. NO, just make this
* configurable via the topology view properties (e.g., a percentage of nodes
* can use such APs) and THEN set the corresponding host property --> if overlay
* code wants to access this information, we might need to add
* {@link HostProperties} to the Simonstrator API.
*
* TODO add distinction for cloudlets and cloud (assuming that cloudlets exhibit
* lower latency), ideally with yet another (TM) host property on the base
* station side: <code><Properties isCloudlet="true" /></code>. NO, again just
* use the groupID of a host as a config setting for this view: e.g., all
* specified groupIDs are Backend hosts vs. direct cloudlets.
*
* FIXME OR: just base this configuration options on the group-ID in the host
* builder?
*
* @author Bjoern Richerzhagen
* @version 1.0, Nov 4, 2015
*/
public class FiveGTopologyView extends AbstractTopologyView<CellLink> {
private Set<MacAddress> cloudlets = new LinkedHashSet<>();
private Set<MacAddress> clouds = new LinkedHashSet<>();
private Set<MacAddress> mobileClients = new LinkedHashSet<>();
private List<MacAddress> mobileClientsList = new LinkedList<>();
private List<MacAddress> cloudsAndCloudletsList = new LinkedList<>();
private FiveGTopologyDatabase database = null;
/**
* Configuration setting: all group IDs of nodes that act as cloudlets
* (e.g., act as basestations with a lower delay, whatever that means w.r.t.
* the specified model)
*/
private Set<String> groupIDsCloudlet = new LinkedHashSet<>();
/**
* Configuration setting: all group IDs that act as cloud (e.g., backend
* servers). Here, the full latency of a connection from a mobile client to
* a network sever somewhere in the Internet is assumed (e.g., as measured
* by Android end user devices)
*/
private Set<String> groupIDsCloud = new LinkedHashSet<>();
/**
*
* @param phy
*/
public FiveGTopologyView(PhyType phy) {
super(phy, true);
}
@XMLConfigurableConstructor({ "phy" })
public FiveGTopologyView(String phy) {
// UMTS is reset with custom type next.
this(PhyType.UMTS);
setPhy(phy);
}
@Override
public Link getBestNextLink(MacAddress source, MacAddress lastHop,
MacAddress currentHop, MacAddress destination) {
return getLinkBetween(source, destination);
}
@Override
public void changedWaypointModel(WaypointModel model) {
// I don't care, I love it.
}
@Override
public void changedObstacleModel(ObstacleModel model) {
// I don't care, I love it.
}
@Override
protected void addedMac(MacLayer mac) {
String groupId = mac.getHost().getProperties().getGroupID();
if (groupIDsCloud.contains(groupId)) {
clouds.add(mac.getMacAddress());
cloudsAndCloudletsList.add(mac.getMacAddress());
} else if (groupIDsCloudlet.contains(groupId)) {
cloudlets.add(mac.getMacAddress());
cloudsAndCloudletsList.add(mac.getMacAddress());
} else {
mobileClients.add(mac.getMacAddress());
mobileClientsList.add(mac.getMacAddress());
}
}
@Override
protected void updateOutdatedLink(CellLink link) {
if (link.isInvalidLink()) {
// cloud <-> cloud or client <-> client link
return;
}
PositionVector pos = getCachedPosition(link.getMobileClient());
int segId = database.getSegmentID(pos.getX(), pos.getY());
if (segId != link.getSegmentId()) {
// update link data
link.setLinkData(database.getEntryFor(segId, link.isCloudlet()));
}
}
@Override
protected CellLink createLink(MacAddress source,
MacAddress destination) {
boolean sourceIsClient = mobileClients.contains(source);
boolean destinationIsClient = mobileClients.contains(destination);
if (sourceIsClient == destinationIsClient) {
// both client or both not client -> not connected
return new CellLink(source, destination);
}
MacAddress mobileClient = sourceIsClient ? source : destination;
CellLink link = new CellLink(source, destination, true,
getPhyType().getDefaultMTU(), mobileClient,
cloudlets.contains(mobileClient));
updateOutdatedLink(link);
return link;
}
@Override
protected List<MacAddress> updateNeighborhood(MacAddress source) {
if (cloudlets.contains(source) || clouds.contains(source)) {
return mobileClientsList;
} else {
assert mobileClients.contains(source);
// Is a client, has all clouds and cloudlets as neighbors
return cloudsAndCloudletsList;
}
}
/*
* Configuration options
*/
/**
* GroupIDs (as specified in the host builder section) that should act as
* clouds (e.g., full measured latency and bandwidth is applied)
*
* @param cloudGroupIDs
*/
@SuppressWarnings("unchecked")
public void setCloudGroups(String[] cloudGroupIDs) {
this.groupIDsCloud = new LinkedHashSet<>(Arrays.asList(cloudGroupIDs));
}
/**
* GroupIDs that act as cloudlets (e.g., lower latency, higher BW) - models
* regional computations facilities.
*
* @param cloudletGroups
*/
@SuppressWarnings("unchecked")
public void setCloudletGroups(String[] cloudletGroups) {
this.groupIDsCloudlet = new LinkedHashSet<>(
Arrays.asList(cloudletGroups));
}
/**
* Set the measurement database providing link quality data for clients
* based on their position.
*
* @param database
*/
public void setDatabase(FiveGTopologyDatabase database) {
assert this.database == null;
this.database = database;
}
/**
* A custom link object supporting dynamic updates of the properties without
* relying on a movement model notification - the client's position is used
* to determine the link performance.
*
* @author Bjoern Richerzhagen
* @version 1.0, Nov 4, 2015
*/
public class CellLink extends DefaultLink {
/**
* Address of the mobile client
*/
private final MacAddress mobileClient;
private FiveGTopologyDatabase.Entry linkData;
private final boolean isUpload;
private final boolean isCloudlet;
private final boolean isInvalidLink;
/**
* An unconnected link
*
* @param source
* @param destination
*/
public CellLink(MacAddress source, MacAddress destination) {
super(source, destination, false, -1, -1, -1, -1);
this.mobileClient = null;
this.isUpload = false;
this.isCloudlet = false;
this.isInvalidLink = true;
}
public CellLink(MacAddress source, MacAddress destination,
boolean isConnected, int mtu, MacAddress mobileClient,
boolean isCloudlet) {
super(source, destination, isConnected, -1, -1, -1, mtu);
this.mobileClient = mobileClient;
this.isCloudlet = isCloudlet;
if (mobileClient.equals(source)) {
isUpload = true;
} else {
assert mobileClient.equals(destination);
isUpload = false;
}
this.isInvalidLink = false;
}
public boolean isInvalidLink() {
return isInvalidLink;
}
public int getSegmentId() {
return linkData == null ? -1 : linkData.getSegmentID();
}
public void setLinkData(FiveGTopologyDatabase.Entry linkData) {
this.linkData = linkData;
}
public MacAddress getMobileClient() {
return mobileClient;
}
public boolean isCloudlet() {
return isCloudlet;
}
@Override
public long getBandwidth(boolean isBroadcast) {
return linkData.getBandwidth(isUpload);
}
@Override
public double getDropProbability() {
return linkData.getDropProbability(isUpload);
}
@Override
public long getLatency() {
return linkData.getLatency(isUpload);
}
}
}
/*
* 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.LinkedHashMap;
import java.util.Map;
import de.tud.kom.p2psim.impl.topology.views.VisualizationTopologyView.VisualizationInjector;
import de.tud.kom.p2psim.impl.topology.views.visualization.world.FiveGVisualization;
import de.tudarmstadt.maki.simonstrator.api.Event;
import de.tudarmstadt.maki.simonstrator.api.EventHandler;
/**
* Abstract base class working on grids of configurable size.
*
* @author Bjoern Richerzhagen
* @version 1.0, Nov 5, 2015
*/
public abstract class AbstractGridBasedTopologyDatabase
implements FiveGTopologyDatabase {
private int gridSize;
private boolean supportCloudlets;
private final Map<Integer, FiveGTopologyDatabase.Entry> cloudEntries;
private final Map<Integer, FiveGTopologyDatabase.Entry> cloudletEntries;
/**
* Grid-based {@link CellularTopologyDatabase} with a grid length (squares)
* of gridSize in meters.
*
* @param gridSize
*/
public AbstractGridBasedTopologyDatabase(int gridSize,
boolean supportCloudlets) {
this.gridSize = gridSize;
this.cloudEntries = new LinkedHashMap<>();
this.cloudletEntries = new LinkedHashMap<>();
}
public void setEnableVis(boolean enableVis) {
if (enableVis == true) {
Event.scheduleImmediately(new EventHandler() {
@Override
public void eventOccurred(Object content, int type) {
VisualizationInjector.injectComponent("5G-Properties", -1,
new FiveGVisualization(
AbstractGridBasedTopologyDatabase.this),
true, true);
}
}, null, 0);
}
}
public void setGridSize(int gridSize) {
this.gridSize = gridSize;
}
public void setSupportCloudlets(boolean supportCloudlets) {
this.supportCloudlets = supportCloudlets;
}
public int getGridSize() {
return gridSize;
}
@Override
public int getSegmentID(double xd, double yd) {
int x = (int) Math.floor(xd / gridSize);
int y = (int) Math.floor(yd / gridSize);
return (((x + y + 1) * (x + y + 2)) / 2 - y);
}
/**
* Create a new {@link Entry} object for the given segmentID. This is called
* at most TWICE for every ID as soon as the ID is required by a node inside
* the given area (once for CLOUD, and once for CLOUDLET if supported).
*
* @param segmentID
* @param isCloudlet
* entry for cloudlets
* @return an {@link Entry} object. For static links, consider using
* {@link StaticEntry} instances provided by
* {@link AbstractCellularTopologyDatabase}
*/
protected abstract Entry createEntryFor(int segmentID, boolean isCloudlet);
@Override
public Entry getEntryFor(int segmentID, boolean isCloudlet) {
if (supportCloudlets && isCloudlet) {
Entry entry = cloudletEntries.get(Integer.valueOf(segmentID));
if (entry == null) {
entry = createEntryFor(segmentID, true);
cloudletEntries.put(Integer.valueOf(segmentID), entry);
}
return entry;
} else {
Entry entry = cloudEntries.get(Integer.valueOf(segmentID));
if (entry == null) {
entry = createEntryFor(segmentID, false);
cloudEntries.put(Integer.valueOf(segmentID), entry);
}
return entry;
}
}
/**
* Very basic entry implementation
*
* @author Bjoern Richerzhagen
* @version 1.0, Nov 5, 2015
*/
public class StaticEntry implements FiveGTopologyDatabase.Entry {
private final int segment;
private final double dropUp, dropDown;
private final long latencyUp, latencyDown, bandwidthUp, bandwidthDown;
public StaticEntry(int segment, double dropUp, double dropDown,
long latencyUp, long latencyDown, long bandwidthUp,
long bandwidthDown) {
this.segment = segment;
this.dropUp = dropUp;
this.dropDown = dropDown;
this.latencyUp = latencyUp;
this.latencyDown = latencyDown;
this.bandwidthUp = bandwidthUp;
this.bandwidthDown = bandwidthDown;
}
@Override
public int getSegmentID() {
return segment;
}
@Override
public double getDropProbability(boolean isUpload) {
return isUpload ? dropUp : dropDown;
}
@Override
public long getLatency(boolean isUpload) {
return isUpload ? latencyUp : latencyDown;
}
@Override
public long getBandwidth(boolean isUpload) {
return isUpload ? bandwidthUp : bandwidthDown;
}
}
}
/*
* 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 de.tud.kom.p2psim.impl.topology.views.FiveGTopologyView;
import de.tud.kom.p2psim.impl.topology.views.FiveGTopologyView.CellLink;
/**
* Database for the {@link FiveGTopologyView} - containing a mapping of
* position IDs to the respective link characteristics.
*
* @author Bjoern Richerzhagen
* @version 1.0, Nov 5, 2015
*/
public interface FiveGTopologyDatabase {
/**
* Calculation of a segment ID based on a position (usually given in
* Cartesian coordinates between 0 and WORLD_SIZE)
*
* @param x
* coordinate
* @param y
* coordinate
* @return
*/
public int getSegmentID(double x, double y);
/**
* Access to the {@link Entry} for a given segmentID. To allow distinction
* between clouds (full latency) and cloudlets (less latency, as the backend
* is "shorter"), we added a boolean "isCloudlet", which may or may not be
* used by the database. It is expected that the link to a cloudlet should
* outperform the link to a cloud.
*
* @param segmentID
* @return
*/
public FiveGTopologyDatabase.Entry getEntryFor(int segmentID,
boolean isCloudlet);
/**
* Data structure for the network parameters of a given segment ID - these
* are directly accessed by the {@link CellLink} object on each call (so
* they should not perform expensive calculations!). We allow a distinction
* between up and download (from the client's perspective) via the provided
* boolean - upload means: from client to station, download means: from
* station to client.
*
* @author Bjoern Richerzhagen
* @version 1.0, Nov 5, 2015
*/
public interface Entry {
/**
* Static segment ID
*
* @return
*/
public int getSegmentID();
/**
* Probability of a packet drop on the link - can even be 1, so that the
* link is virtually disconnected.
*
* @return
*/
public double getDropProbability(boolean isUpload);
/**
* Latency on the link (RTT/2)
*
* @return
*/
public long getLatency(boolean isUpload);
/**
* Bandwidth on the link
*
* @return
*/
public long getBandwidth(boolean isUpload);
}
}
/*
* 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.Random;
import de.tud.kom.p2psim.impl.topology.views.FiveGTopologyView;
import de.tudarmstadt.maki.simonstrator.api.Randoms;
import de.tudarmstadt.maki.simonstrator.api.Time;
/**
* Simple random grid {@link FiveGTopologyDatabase} for the
* {@link FiveGTopologyView}.
*
* @author Bjoern Richerzhagen
* @version 1.0, Nov 5, 2015
*/
public class RandomGridDatabase extends AbstractGridBasedTopologyDatabase {
private Random rnd = Randoms.getRandom(RandomGridDatabase.class);
public RandomGridDatabase() {
super(100, true);
}
@Override
protected Entry createEntryFor(int segmentID, boolean isCloudlet) {
long latRnd = ((long) (rnd.nextDouble() * 200 * Time.MILLISECOND))
+ 50 * Time.MILLISECOND
+ (isCloudlet ? 0 : 200 * Time.MILLISECOND);
double dropRnd = rnd.nextDouble();
return new StaticEntry(segmentID, dropRnd, dropRnd, latRnd, latRnd,
1000000, 1000000);
}
}
/*
* 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.visualization.world;
import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import javax.swing.JComponent;
import de.tud.kom.p2psim.impl.topology.views.FiveGTopologyView;
import de.tud.kom.p2psim.impl.topology.views.VisualizationTopologyView.VisualizationInjector;
import de.tud.kom.p2psim.impl.topology.views.fiveg.AbstractGridBasedTopologyDatabase;
import de.tud.kom.p2psim.impl.topology.views.fiveg.FiveGTopologyDatabase.Entry;
import de.tudarmstadt.maki.simonstrator.api.Time;
/**
* Visualization for the {@link FiveGTopologyView}
*
* @author Bjoern Richerzhagen
* @version 1.0, Nov 5, 2015
*/
public class FiveGVisualization extends JComponent {
protected BufferedImage image;
protected volatile boolean needsRedraw = true;
private final AbstractGridBasedTopologyDatabase database;
public FiveGVisualization(AbstractGridBasedTopologyDatabase database) {
setBounds(0, 0, VisualizationInjector.getWorldX(),
VisualizationInjector.getWorldY());
setOpaque(true);
setVisible(true);
this.database = database;
image = new BufferedImage(VisualizationInjector.getWorldX(),
VisualizationInjector.getWorldY(), BufferedImage.TYPE_INT_ARGB);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (needsRedraw) {
redraw();
}
Graphics2D g2 = (Graphics2D) g;
g2.drawImage(image, 0, 0, null);
}
protected void redraw() {
needsRedraw = false;
Graphics2D g2 = (Graphics2D) image.getGraphics();
Composite c = g2.getComposite();
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR, 0.0f));
Rectangle2D.Double rect = new Rectangle2D.Double(0, 0,
VisualizationInjector.getWorldX(),
VisualizationInjector.getWorldY());
g2.fill(rect);
g2.setComposite(c);
try {
drawEntries(g2);
} catch (RuntimeException e) {
needsRedraw = true;
}
}
private void drawEntries(Graphics2D g2) {
// Iterate over grid coordinates
int stepSize = database.getGridSize();
double maxLatency = 0;
double minLatency = Double.MAX_VALUE;
boolean isUpload = false;
for (int x = 0; x < VisualizationInjector.getWorldX(); x += stepSize) {
for (int y = 0; y < VisualizationInjector
.getWorldY(); y += stepSize) {
// TODO add checkbox for cloudlets?
Entry entry = database.getEntryFor(database.getSegmentID(x, y),
false);
if (entry.getLatency(isUpload) > maxLatency) {
maxLatency = entry.getLatency(isUpload);
}
if (entry.getLatency(isUpload) < minLatency) {
minLatency = entry.getLatency(isUpload);
}
}
}
for (int x = 0; x < VisualizationInjector.getWorldX(); x += stepSize) {
for (int y = 0; y < VisualizationInjector
.getWorldY(); y += stepSize) {
// TODO add checkbox for cloudlets?
Entry entry = database.getEntryFor(database.getSegmentID(x, y),
false);
// TODO add checkbox for upload/download toggle?
// Latency
double latencyFactor = (entry.getLatency(isUpload) - minLatency)
/ (maxLatency - minLatency);
g2.setColor(
new Color(255, 0, 0, 10 + (int) (40 * latencyFactor)));
g2.fillRect(x, y, stepSize, stepSize);
// Drop-Prob
g2.setColor(new Color(255, 0, 0,
10 + (int) (100 * entry.getDropProbability(isUpload))));
g2.setStroke(new BasicStroke(
(float) (10 * entry.getDropProbability(isUpload))));
g2.drawRect(x, y, stepSize, stepSize);
g2.setColor(new Color(0, 0, 0, 100));
g2.drawString(
"L: " + entry.getLatency(isUpload) / Time.MILLISECOND,
x + 10, y + 10);
g2.drawString("D: "
+ (int) (entry.getDropProbability(isUpload) * 100),
x + 10, y + 25);
}
}
}
}
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