/* * 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 . * */ 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) * . 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: . 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 { private Set cloudlets = new LinkedHashSet<>(); private Set clouds = new LinkedHashSet<>(); private Set mobileClients = new LinkedHashSet<>(); private List mobileClientsList = new LinkedList<>(); private List 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 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 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 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); } } }