/*
* Copyright (c) 2005-2011 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
* The Modular Network layer aims at being most flexible by allowing every * aspect of a network layer to be modeled on its own - as a module. Like * "building blocks", these modules can be customized in the simulator * configuration file and put together to form the whole network layer. *
* ** The Modular Network Layer currently supports modules of the type *
* For information how to configure a modular network layer, please consult * ModularNetLayerFactory. *
** To understand particular module types and to write a module yourself, please * consult its abstract strategy class. *
* * @see FragmentingStrategy * @see JitterStrategy * @see LatencyStrategy * @see PacketSizingStrategy * @see PLossStrategy * @see PositioningStrategy * @see TrafficControlStrategy * @see ModularNetLayerFactory * @author Leo Nobach * */ public class ModularNetLayer extends AbstractNetLayer { private AbstractModularSubnet subnet; /** * Creates a new Modular Network layer. This should be only called from the * ModularNetLayerFactory * * @param subnet * @param maxBW * @param hostMeta * @param position * @param id * @param device * Device-Type of this Host */ ModularNetLayer(SimHost host, AbstractModularSubnet subnet, BandwidthImpl maxBW, NetMeasurementDB.Host hostMeta, Location position, IPv4NetID id) { super(host, id, maxBW, position, hostMeta); this.subnet = subnet; } @Override public void initialize() { subnet.registerNetLayer(this); goOnline(); super.initialize(); } public String toString() { if (hostMeta != null) { City city = hostMeta.getCity(); Region region = city.getRegion(); Country country = region.getCountry(); return "ModNetLayer(" + getNetID() + ", " + city + ", " + region + ", " + country + ")"; } return "ModNetLayer(" + getLocalInetAddress() + " (no location info))"; } @Override protected boolean isSupported(TransProtocol protocol) { return protocol.equals(TransProtocol.UDP); } Object trafCtrlMetadata = null; /** * Convenience method for send() * * @param netMsg * @param receiver */ private void sendNetMessage(NetMessage netMsg, NetID receiver) { if (this.isOnline()) { NetLayerLiveMonitoring.getOfflineMsgDrop().noDropMessage(); subnet.getStrategies() .getTrafficControlStrategy() .onSendRequest(this.new SendContextImpl(), netMsg, receiver); } } /** * Convenience method for send() * * @param msg * @param receiver */ private void dropOfflineNetMessage(Message msg, NetID receiver) { NetMessage netMsg = new IPv4Message(msg, receiver, this.getLocalInetAddress()); //log.debug("Dropping message " + msg + ", because sender " + this // + " is offline."); NetLayerLiveMonitoring.getOfflineMsgDrop().droppedMessage(); if (hasAnalyzer) { netAnalyzerProxy.netMsgEvent(netMsg, getHost(), Reason.DROP); } } @Override public void send(Message msg, NetID receiver, NetProtocol protocol) { if (msg instanceof AbstractTransMessage) { if (protocol != NetProtocol.IPv4) throw new AssertionError( "Currently, the simulator only supports IPv4. " + msg.getClass().getSimpleName()); if (this.isOnline()) { TransProtocol usedTransProtocol = ((AbstractTransMessage) msg) .getProtocol(); if (this.isSupported(usedTransProtocol)) { NetMessage netMsg = new ModularNetMessage(msg, receiver, getNetID(), subnet.getStrategies(), NetProtocol.IPv4); // IPv6 currently not supported sendNetMessage(netMsg, receiver); if (((AbstractTransMessage) msg).getCommId() == -1) { int assignedMsgId = subnet.determineTransMsgNumber(msg); ((AbstractTransMessage) msg).setCommId(assignedMsgId); } } else throw new IllegalArgumentException("Transport protocol " + usedTransProtocol + " not supported by this NetLayer implementation."); } else { int assignedMsgId = subnet.determineTransMsgNumber(msg); ((AbstractTransMessage) msg).setCommId(assignedMsgId); dropOfflineNetMessage(msg, receiver); } } else { throw new AssertionError( "Can only send messages of class AbstractTransMessage or " + "subclasses of it through the network layer, but the message class was " + msg.getClass().getSimpleName()); } } class SendContextImpl implements ISendContext { @Override public Object getTrafCtrlMetadata() { return trafCtrlMetadata; } @Override public void setTrafCtrlMetadata(Object trafCtrlMetadata) { ModularNetLayer.this.trafCtrlMetadata = trafCtrlMetadata; } @Override public void sendSubnet(NetMessage netMsg) { NetLayerLiveMonitoring.getTrafCtrlMsgDrop().noDropMessage(); if (hasAnalyzer) { netAnalyzerProxy.netMsgEvent(netMsg, getHost(), Reason.SEND); } ModularNetLayer.this.getSubnet().send(netMsg); } @Override public void dropMessage(NetMessage netMsg) { //log.debug("Dropping message " + netMsg + ", because the sender's (" // + ModularNetLayer.this // + ") traffic control mechanism has decided it."); NetLayerLiveMonitoring.droppedMessageTrafCtrl(netMsg); if (hasAnalyzer) { netAnalyzerProxy.netMsgEvent(netMsg, getHost(), Reason.DROP); } } @Override public Bandwidth getMaxBW() { return ModularNetLayer.this.getMaxBandwidth(); } } // TODO @Override @Deprecated public void receive(NetMessage message) { throw new IllegalStateException( "The method receive(NetMessage) is deprecated in the Modular Network Layer."); } /** * Receiving a Message without additional information on the Subnet-Context. * This is only used by the SimpleModularSubnet, as it has no Topology or * Channels. * * @param message * @param netLayerOfSender */ public void receive(ModularNetMessage message, ModularNetLayer netLayerOfSender) { ReceiveContextImpl ctx = new ReceiveContextImpl( netLayerOfSender.getMaxBandwidth(), getMaxBandwidth()); subnet.getStrategies().getTrafficControlStrategy() .onReceive(ctx, message); } class ReceiveContextImpl implements IReceiveContext { private Bandwidth senderBW; private Bandwidth receiverBW; public ReceiveContextImpl(Bandwidth senderBW, Bandwidth receiverBW) { this.senderBW = senderBW; this.receiverBW = receiverBW; } @Override public Object getTrafCtrlMetadata() { return trafCtrlMetadata; } @Override public void setTrafCtrlMetadata(Object trafCtrlMetadata) { ModularNetLayer.this.trafCtrlMetadata = trafCtrlMetadata; } @Override public void arrive(NetMessage message) { NetLayerLiveMonitoring.getTrafCtrlMsgDrop().noDropMessage(); if (ModularNetLayer.this.isOnline()) { NetLayerLiveMonitoring.getOfflineMsgDrop().noDropMessage(); NetLayerLiveMonitoring.getRoutingMsgDrop().noDropMessage(); NetID myID = getNetID(); if (hasAnalyzer) { netAnalyzerProxy.netMsgEvent(message, getHost(), Reason.RECEIVE); } NetMsgEvent event = new NetMsgEvent(message, ModularNetLayer.this); Collection