/*
* 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
* The {@link IWifiRemoteStation} can be used to store state information for
* every station.
*
* If a new Rate Manager is implemented, it should be added to the * {@link RateManagerTypes} and in the create method in this class. *
*
*
* This class is based on NS3 (src/wifi/model/wifi-remote-station-manager.cc) by
* Mathieu Lacage
* A higher BroadcastDataMode is not usually in the real world!
*
* @param broadcastDataMode
* The new {@link WifiMode} for the broadcast.
*/
public void setBroadcastDataMode(WifiMode broadcastDataMode) {
this.broadcastDataMode = broadcastDataMode;
}
/**
* Adds a {@link WifiMode} to the basicModes. It can only added as basic
* mode, if it is registered as a normal mode.
*
* @param mode
* The {@link WifiMode} which should be added to the basicModes.
*/
public void addBasicMode(WifiMode mode) {
if (modes.contains(mode)) {
if (!basicModes.contains(mode)) {
basicModes.add(mode);
}
} else {
throw new AssertionError(
"try to add a mode to the basicModes, which is not stored as a common mode");
}
}
/**
* Gets all Modes.
*
* @return All {@link WifiMode}s for this RateManager.
*/
protected Listnull
if the requested Type is not available.
*/
public static AbstractRateManager createRateManager(Ieee80211AdHocMac mac,
RateManagerTypes rateManagerType, Standard_802_11 standard) {
if (rateManagerType.equals(RateManagerTypes.IDEAL)) {
return new IdealRateManager(standard.getWifiModes(),
standard.getDefaultMode(), mac);
} else if (rateManagerType.equals(RateManagerTypes.ARF)) {
return new ArfRateManager(standard.getWifiModes(),
standard.getDefaultMode(), mac);
}
return null;
}
/**
* A hashMap of information of {@link IWifiRemoteStation}s. To every
* {@link MacAddress} will be stored an own {@link IWifiRemoteStation}.
*/
private Map
*/
final public void reportDataOk(MacAddress address, double ackSnr,
WifiMode ackMode) {
IWifiRemoteStation station = getStation(address);
doReportDataOk(station, ackSnr, ackMode);
}
/**
* Should be invoked after calling ReportRtsFailed if no RTS should be more
* resent.
*/
final public void reportFinalRtsFailed(MacAddress address) {
IWifiRemoteStation station = getStation(address);
doReportFinalRtsFailed(station);
}
/**
* Should be invoked after calling ReportDataFailed if no resent of the data
* packet should be executed.
*/
final public void reportFinalDataFailed(MacAddress address) {
IWifiRemoteStation station = getStation(address);
doReportFinalDataFailed(station);
}
/**
*
* Should be invoked whenever a packet is successfully received.
*
*
* @param address
* remote address
* @param rxSnr
* the snr of the packet received
* @param txMode
* the transmission mode used for the packet received.
*/
final public void reportRxOk(MacAddress address, double rxSnr,
WifiMode txMode) {
IWifiRemoteStation station = getStation(address);
doReportRxOk(station, rxSnr, txMode);
}
/**
* Returns a station to the given {@link MacAddress}. It does a lookup in a
* hashtable after the {@link IWifiRemoteStation}. If no
* {@link IWifiRemoteStation} found, then will be create a new
* {@link IWifiRemoteStation}.
*
* @param address
* The {@link MacAddress} to the station.
* @return A stored or new {@link IWifiRemoteStation}.
*/
private IWifiRemoteStation getStation(MacAddress address) {
IWifiRemoteStation station = remoteStations.get(address);
if (station == null) {
station = doCreateWifiRemoteStation(address);
remoteStations.put(address, station);
}
assert station != null : "Station should not be null!";
return station;
}
/**
* Gets the DataMode for a unicast transfer to the given {@link MacAddress}.
* The answer is dependent on the used implementation of the RateManager. In
* normal case, the answer is {@link WifiMode} from all available Modes.
*
* @param address
* The {@link MacAddress} of the receiver.
* @return A {@link WifiMode} from {@link AbstractRateManager#modes}.
*/
public final WifiMode getUnicastDataMode(MacAddress address) {
IWifiRemoteStation station = getStation(address);
return doGetUnicastDataMode(station);
}
/**
* Gets {@link WifiMode} for the RTS Message for the given receiver. It is
* normal a {@link WifiMode}, which is declared as mandatory.
*
*
* @param address
* The {@link MacAddress} of the receiver.
* @return The {@link WifiMode} for the RTS Message to the given receiver.
*/
public final WifiMode getRtsMode(MacAddress address) {
IWifiRemoteStation station = getStation(address);
return doGetRtsMode(station);
}
/**
* Chose the defaultMode if not an other {@link WifiMode} is declared as
* BroadcastMode.
* The BroadcastMode can be set with
* {@link AbstractRateManager#setBroadcastDataMode(WifiMode)}.
*
* @return The {@link WifiMode} for Broadcasts.
*/
public final WifiMode getBroadcastDataMode() {
if (broadcastDataMode == null) {
return defaultMode;
}
return broadcastDataMode;
}
/**
* Gets the {@link WifiMode} for the answer of a RTS Message. For the
* calculation of the WifiMode, it is used the algorithm of the IEEE
* Standard.
*
* @param rtsMode
* The {@link WifiMode} of the received RTS Message.
* @return The {@link WifiMode} for CTS Message.
*/
public final WifiMode getCtsMode(WifiMode rtsMode) {
return getControlAnswerMode(rtsMode);
}
/**
* Gets the {@link WifiMode} for the acknowledgment of the data. For the
* calculation of the WifiMode, it is used the algorithm of the IEEE
* Standard.
*
* @param dataMode
* The {@link WifiMode} of the received Data.
* @return The {@link WifiMode} for the ACK Message.
*/
public final WifiMode getAckMode(WifiMode dataMode) {
return getControlAnswerMode(dataMode);
}
/*
* copied from NS3::WifiRemoteStationManager
*/
protected WifiMode getControlAnswerMode(WifiMode reqMode) {
/**
* The standard has relatively unambiguous rules for selecting a control
* response rate (the below is quoted from IEEE 802.11-2007, Section
* 9.6):
*
* To allow the transmitting STA to calculate the contents of the
* Duration/ID field, a STA responding to a received frame shall
* transmit its Control Response frame (either CTS or ACK), other than
* the BlockAck control frame, at the highest rate in the
* BSSBasicRateSet parameter that is less than or equal to the rate of
* the immediately previous frame in the frame exchange sequence (as
* defined in 9.12) and that is of the same modulation class (see 9.6.1)
* as the received frame...
*/
WifiMode mode = getDefaultMode();
boolean found = false;
// First, search the BSS Basic Rate set
for (WifiMode bss : getBSSBasicRateSet()) {
if ((!found || bss.getPhyRate() > mode.getPhyRate())
&& bss.getPhyRate() <= reqMode.getPhyRate()
&& bss.getModClass() == reqMode.getModClass()) {
mode = bss;
// We've found a potentially-suitable transmit rate, but we
// need to continue and consider all the basic rates before
// we can be sure we've got the right one.
found = true;
}
}
// If we found a suitable rate in the BSSBasicRateSet, then we are
// done and can return that mode.
if (found) {
return mode;
}
/**
* If no suitable basic rate was found, we search the mandatory rates.
* The standard (IEEE 802.11-2007, Section 9.6) says:
*
* ...If no rate contained in the BSSBasicRateSet parameter meets these
* conditions, then the control frame sent in response to a received
* frame shall be transmitted at the highest mandatory rate of the PHY
* that is less than or equal to the rate of the received frame, and
* that is of the same modulation class as the received frame. In
* addition, the Control Response frame shall be sent using the same PHY
* options as the received frame, unless they conflict with the
* requirement to use the BSSBasicRateSet parameter.
*
* Note that we're ignoring the last sentence for now, because there is
* not yet any manipulation here of PHY options.
*/
for (WifiMode thismode : modes) {
/*
* If the rate:
*
* - is a mandatory rate for the PHY, and - is equal to or faster
* than our current best choice, and - is less than or equal to the
* rate of the received frame, and - is of the same modulation class
* as the received frame
*
* ...then it's our best choice so far.
*/
if (thismode.isMandatory()
&& (!found || thismode.getPhyRate() > mode.getPhyRate())
&& thismode.getPhyRate() <= reqMode.getPhyRate()
&& thismode.getModClass() == reqMode.getModClass()) {
mode = thismode;
// As above; we've found a potentially-suitable transmit
// rate, but we need to continue and consider all the
// mandatory rates before we can be sure we've got the right
// one.
found = true;
}
}
/**
* If we still haven't found a suitable rate for the response then
* someone has messed up the simulation config. This probably means that
* the WifiPhyStandard is not set correctly, or that a rate that is not
* supported by the PHY has been explicitly requested in a
* WifiRemoteStationManager (or descendant) configuration.
*
* Either way, it is serious - we can either disobey the standard or
* fail, and I have chosen to do the latter...
*/
assert found : ("Can't find response rate for " + reqMode + ". Check standard and selected rates match.");
return mode;
}
/**
* Gets the default Mode.
*
* @return Returns the default Mode.
*/
protected WifiMode getDefaultMode() {
return defaultMode;
}
/**
* Gets the BSS Basic Rate Set for this Rate Manager. Actually, it is only
* the default Mode.
*
* @return Returns a Set of {@link WifiMode}s.
*/
protected Set
* This is only a helper to calculate the SNR in the AdHocMac.
*/
public double calculateActuallySNR(Location startPosition,
Location targetPosition, WifiMode mode, double txPowerDbm) {
InterferenceHelper helper = mac.getWifiTopologyView()
.getInterferenceHelper();
double noiseInterferenceW = helper
.calculateNoiseInterferenceW(targetPosition);
double rxPowerDbm = helper.getLossModel().getRxPowerDbm(
txPowerDbm + helper.getTxGainDbm(), startPosition,
targetPosition)
+ helper.getRxGainDbm();
return helper.calculateSnr(PropagationLossModel.dbmToW(rxPowerDbm),
noiseInterferenceW, mode);
}
}