WifiTopologyView.java 16.4 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
/*
 * 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.wifi;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import de.tud.kom.p2psim.api.common.SimHost;
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.scenario.ConfigurationException;
import de.tud.kom.p2psim.api.topology.views.TopologyView;
import de.tud.kom.p2psim.api.topology.views.wifi.phy.ErrorRateModel;
import de.tud.kom.p2psim.api.topology.views.wifi.phy.PropagationLossModel;
import de.tud.kom.p2psim.api.topology.views.wifi.phy.WifiMode;
import de.tud.kom.p2psim.api.topology.views.wifi.phy.WifiPhy.Standard_802_11;
import de.tud.kom.p2psim.api.topology.views.wifi.phy.WifiPhy.WifiPreamble;
import de.tud.kom.p2psim.impl.linklayer.mac.wifi.Ieee80211AdHocMac;
import de.tud.kom.p2psim.impl.topology.views.RangedLink;
import de.tud.kom.p2psim.impl.topology.views.RangedTopologyView;
import de.tud.kom.p2psim.impl.topology.views.wifi.phy.InterferenceHelper;
import de.tudarmstadt.maki.simonstrator.api.Message;
45
46
47
import de.tudarmstadt.maki.simonstrator.api.Monitor;
import de.tudarmstadt.maki.simonstrator.api.Monitor.Level;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;

/**
 * Extends the RangedTopologyView for a second range, which contains all
 * neighbors, who can sense the signal.<br>
 * 
 * In the first range, it is possible to communicate with the other station
 * (Link.isConnected() should be true). <br>
 * In the second range, it is only a signal on the medium, which cannot be read
 * from the other station, but the other station can be sense, that the medium
 * is busy. Rather, the second range can be called CS (Carrier Sense) Range.
 * <p>
 * Additionally this class is the interface to the {@link InterferenceHelper}.
 * This mean, that this class can add transfers and interferences to the
 * InterferenceHelper. On the other hand, this class can get the PER to a
 * packet.
 * <p>
 * This WifiTopology supported only one channel for all peers and one TxPower
 * for all peers.<br>
 * The extending for multiple channels, the structure of neighbors must be
 * changed and for every channel an own {@link InterferenceHelper}. For the
 * TxPower, to all MACs, must be stored the txPower and the resulting ranges.
 * 
 * 
 * TODO: Add Interface for Carrier Sensing
 * 
 * @author Christoph Muenker
 * @version 1.0, 15.09.2012
 */
public class WifiTopologyView extends RangedTopologyView {

	/**
	 * Stores the radius of the carrier sense range, which is computed based on
	 * the values for the two parameters maxTxPowerDbm and csDbm.
	 */
	private double csRange;

	/**
	 * The SAT denotes the Signal Attention Threshold and represents the mean
	 * minimal signal power, which should be used as noise for the calculation
	 * of the SNR. In other words, a signal lower as this level can be ignored
	 * and does not influence, for instance, the cs-range.<br>
	 * The Signal Attention Threshold is not specified in ns-3 but comes from
	 * OMNET++ and is specified in ChannelControl.ned and set to -110dBm.
	 */
	private double satDbm = -110;

	/**
	 * Specifies the Signal Attention Threshold in Watt.
	 */
	private double satW = PropagationLossModel.dbmToW(satDbm);

	/**
	 * rxSensitivityDbm denotes the receive sensitivity of a device and
	 * specifies down to which value a Wi-Fi card can still read the signal from
	 * the medium. In ns-3, this value is represented by the attribute
	 * "EnergyDetectionThreshold" in the class yans-wifi-phy.cc and set to
	 * -96dBm.
	 */
	private double rxSensitivityDbm = -96;

	/**
	 * Specifies the receive sensitivity in Watt.
	 */
	private double rxSensitivityW = PropagationLossModel
			.dbmToW(rxSensitivityDbm);

	/**
	 * csDbm denotes the carrier sense sensitivity of a device and specifies
	 * down to which value a Wi-Fi card can still sense (but not read) a signal.
	 * If signals above this level are received, the card knows that the medium
	 * is busy. In ns-3, this value is represented by the attribute
	 * "CcaMode1Threshold" in the class yans-wifi-phy.cc and set to -99dBm.
	 */
	private double csDbm = -99;

	/**
	 * Specifies the carrier sense sensitivity in Watt.
	 */
	private double csW = PropagationLossModel.dbmToW(csDbm);

	/**
	 * Stores the frequency of the utilized IEEE802.11 standard.
	 */
	private long frequency = 0;

	/**
	 * Specifies the transmission power of a all Wi-Fi chips, which simulated in
	 * a simulation.
	 */
	private double maxTxPowerDbm = 0;

	private Map<MacAddress, List<MacAddress>> cachedCSNeighbors = new HashMap<MacAddress, List<MacAddress>>();

	private InterferenceHelper interferenceHelper;
	
	private Standard_802_11 standard_802_11;

	public WifiTopologyView(PhyType phy) {
		super(phy, 100.0);
		interferenceHelper = new InterferenceHelper(this);
	}

	@XMLConfigurableConstructor({ "phy" })
	public WifiTopologyView(String phy) {
		this(PhyType.WIFI);
		setPhy(phy);

	}

	/**
	 * Updates the carrier sense neighborhood and cache the neighborhood.
	 * Additionally it executes the super method.
	 * 
	 * @param source
	 * @return
	 */
	@Override
	protected List<MacAddress> updateNeighborhood(MacAddress source) {

		List<MacAddress> csNeighbors = new ArrayList<MacAddress>();
		for (MacAddress neighbor : allMacAddresses) {
			if (!source.equals(neighbor)) {
				RangedLink link = getLinkBetween(source, neighbor);
				if (link.getNodeDistance() < csRange) {
					assert !neighbor.equals(source);
					csNeighbors.add(neighbor);
				}
			}
		}

		cachedCSNeighbors.put(source, csNeighbors);

		return super.updateNeighborhood(source);
	}

	/**
	 * Gets all Neighbors which are in the carrier sense neighborhood of the
	 * given {@link MacAddress}.
	 * 
	 * @param source
	 *            The MacAddress
	 * @return The unmodifable list of carrier sense neighborhood to the given
	 *         {@link MacAddress}.
	 */
	public List<MacAddress> getCarrierSenseNeighbors(MacAddress source) {
		return Collections.unmodifiableList(getCachedCSNeighbors(source));
	}

	private List<MacAddress> getCachedCSNeighbors(MacAddress source) {
		// updates the cachedCSNeighbors, if it is outdated
		getNeighbors(source);
		return cachedCSNeighbors.get(source);
	}

	public InterferenceHelper getInterferenceHelper() {
		return interferenceHelper;
	}

	protected void setCSRange(double csRange) {
		this.csRange = csRange;
	}

	public PropagationLossModel getPropagationLossModel() {
		return interferenceHelper.getLossModel();
	}

	public ErrorRateModel getErrorRateModel() {
		return interferenceHelper.getErrorModel();
	}

	/**
	 * Sets the new propagationLossModel in {@link InterferenceHelper},
	 * additionally it sets the frequency for the lossModel which is used.
	 * Further, it executes a update of the ranges.
	 * 
	 * @param lossModel
	 *            The new lossModel.
	 */
	public void setPropagationLossModel(PropagationLossModel lossModel) {
		lossModel.setFrequency(frequency);
		interferenceHelper.setLossModel(lossModel);
		updateRanges();
	}

	/**
	 * Sets the new ErrorRateModel in {@link InterferenceHelper}.Further, it
	 * executes a update of the ranges.
	 * 
	 * @param errorRateModel
	 *            The new errorRateModel.
	 */
	public void setErrorRateModel(ErrorRateModel errorRateModel) {
		interferenceHelper.setErrorModel(errorRateModel);
		updateRanges();
	}

	/**
	 * Add a new transfer to the {@link InterferenceHelper}. This mean, that
	 * this will be added as Interference and it is possible to get to the given
	 * message a Packet Error Rate (PER), to check for a drop.
	 * 
	 * @param start
	 *            The start time in microseconds
	 * @param end
	 *            The end time in microseconds
	 * @param sourcePosition
	 *            The position of the source
	 * @param txPowerDbm
	 *            The transmission power in dBm
	 * @param id
	 *            The message which is the identifier for the calculation of the
	 *            PER
	 * @param dataMode
	 *            The {@link WifiMode} for the data
	 * @param preamble
	 *            The {@link WifiMode} of the preamble
	 * @param host
	 *            The host which starts this transfer.
	 * @param sourceAddress
	 *            The {@link MacAddress} of the source, which stats this
	 *            transfer
	 */
271
	public void addTransfer(long start, long end, Location sourcePosition,
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
			double txPowerDbm, Message id, WifiMode dataMode,
			WifiPreamble preamble, SimHost host, MacAddress sourceAddress) {
		interferenceHelper.addTransfer(start, end, sourcePosition, txPowerDbm,
				id, dataMode, preamble, host, sourceAddress);
	}

	/**
	 * Add a new Interference to the {@link InterferenceHelper}. This should be
	 * used, if you want to simulate a transfer, but you are not interested
	 * about the Packet Error Rate of this message.
	 * 
	 * @param start
	 *            The start time in microseconds
	 * 
	 * @param end
	 *            The end time in microseconds
	 * @param sourcePosition
	 *            The position of the source
	 * @param txPowerDbm
	 *            The transmission power in dBm
	 * @param dataMode
	 *            The {@link WifiMode} of this interference
	 * @param sourceAddress
	 *            The sourceAddress of this interference (It will be used the
	 *            neighborhood of this peer, to inform about carrier sensing).
	 */
298
	public void addInterference(long start, long end, Location sourcePosition,
299
300
301
302
303
304
305
306
307
308
309
310
			double txPowerDbm, WifiMode dataMode, MacAddress sourceAddress) {
		interferenceHelper.addInterference(start, end, sourcePosition,
				txPowerDbm, dataMode, sourceAddress);
	}

	/**
	 * Calculates the Packer Error Rate (PER) for the message at the given
	 * Position.
	 * 
	 * @param msg
	 *            The message which was added as interference (or rather as ID)
	 *            with
311
	 *            {@link WifiTopologyView#addInterference(long, long, Location, double, WifiMode, MacAddress)}
312
313
314
315
316
317
318
	 *            to the {@link InterferenceHelper}.
	 * @param pos
	 *            The position for that the PER should be calculated for this
	 *            message.
	 * @return The Packet Error Rate (PER) for the message at the given
	 *         Position.
	 */
319
	public double calculatePer(Message msg, Location pos) {
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
		return interferenceHelper.calculatePer(msg, pos);
	}

	/**
	 * Gets all {@link MacAddress} which are known by this {@link TopologyView}
	 * 
	 * @return An unmodifiable list of all known mac addresses
	 */
	public List<MacAddress> getAllMacAddresses() {
		return Collections.unmodifiableList(allMacAddresses);
	}

	/**
	 * Sets the frequency, which should be used. This will be multiple called
	 * from the MAC-Layer, so we check for the condition, that all MACs have the
	 * same frequency.<br>
	 * Additionally the ranges will be updated
	 * 
	 * @param frequency
	 *            The frequency, which will be used from the MAC-Layer.
	 */
	protected void setFrequency(long frequency) {
		if (this.frequency != 0 && this.frequency != frequency) {
			throw new ConfigurationException(
					"Using different Frequencies on the same Topology-View. This is not supported!");
		}
		getPropagationLossModel().setFrequency(frequency);
		this.frequency = frequency;
		updateRanges();
	}

	/**
	 * Sets the transmission power in dBm, which should be used to calculate the
	 * ranges. This will be multiple called from the MAC-Layer, so we check for
	 * maximal transmission power and use the maximal transmission power for the
	 * calculation of the ranges.<br>
	 * <br>
	 * Additionally the ranges will be updated
	 * 
	 * @param txPowerDbm
	 *            the transmission power in dBm
	 */
	protected void setTxPowerDbm(double txPowerDbm) {
		// FIXME: Possible to store for every node, and for every node an own
		// range!
		this.maxTxPowerDbm = Math.max(maxTxPowerDbm, txPowerDbm);
		updateRanges();
	}

	/**
	 * Updates the ranges, which will be used to fill the caches of the
	 * neighborhood.
	 */
	private void updateRanges() {
		double csRange = interferenceHelper.calculateMaximalRadius(
				maxTxPowerDbm, csDbm);
		double range = interferenceHelper.calculateMaximalRadius(maxTxPowerDbm,
				rxSensitivityDbm);
		double satRange = interferenceHelper.calculateMaximalRadius(
				maxTxPowerDbm, satDbm);
380
381
382
383
384
		System.out.println("satRange: " + satRange + " csRange: " + csRange
				+ " range: " + range);
		Monitor.log(WifiTopologyView.class, Level.INFO,
				"WiFi underlay ranges: satRange: " + satRange + " csRange: "
						+ csRange + " range: " + range);
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
		setRange(range);
		setCSRange(csRange);

	}

	/**
	 * Sets the used standard of the MAC-Layer. This will be called multiple,
	 * and we check for different standards. If we found different standards, we
	 * throw an exception, because we only support a homogeneous network of the
	 * same standard.
	 * 
	 * @param standard
	 *            The standard which is used by the MAC-Layer.
	 */
	protected void setStandard_802_11(Standard_802_11 standard) {
		if (standard_802_11 != null && !standard_802_11.equals(standard)) {
			throw new ConfigurationException(
					"Using different IEEE 802.11 Standards on the same Topology-View. This is not supported!");
		}
		this.standard_802_11 = standard;
	}

	@Override
	protected void addedMac(MacLayer mac) {
		super.addedMac(mac);
		Ieee80211AdHocMac wifiMac = (Ieee80211AdHocMac) mac;
		// sets the standard, txPower and the frequency, which is using of the
		// mac.
		// Additionally it will be checked for a homogeneous network of this
		// parameter.
		setStandard_802_11(wifiMac.getStandard_802_11());
		setTxPowerDbm(wifiMac.getTxPowerDdm());
		setFrequency(wifiMac.getFrequency());
	}

	/**
	 * Sets the Signal Attention Threshold in dBm for the
	 * {@link InterferenceHelper}.
	 * 
	 * @param satDbm
	 *            The Signal Attention Threshold in dBm.
	 */
	public void setSatDbm(double satDbm) {
		this.satDbm = satDbm;
		this.satW = PropagationLossModel.dbmToW(satDbm);
		this.interferenceHelper.setSatDbm(satDbm);
	}

	/**
	 * Sets the Signal Attention Threshold in watt for the
	 * {@link InterferenceHelper}
	 * 
	 * @param satW
	 *            The Signal Attention Threshold in watt
	 */
	public void setSatW(double satW) {
		this.satW = satW;
		this.satDbm = PropagationLossModel.wToDbm(satW);
		this.interferenceHelper.setSatDbm(satDbm);
	}

	/**
	 * Sets the carrier sense threshold.
	 * 
	 * @param csDbm
	 *            the carrier sense threshold in dBm
	 */
	public void setCsDbm(double csDbm) {
		this.csDbm = csDbm;
		this.csW = PropagationLossModel.dbmToW(csDbm);
	}

	/**
	 * Sets the carrier sense threshold.
	 * 
	 * @param csW
	 *            the carrier sense threshold in watt
	 */
	public void setCsW(double csW) {
		this.csW = csW;
		this.csDbm = PropagationLossModel.wToDbm(csW);
	}

	/**
	 * Sets the receive sensitivity threshold.
	 * 
	 * @param rxSensitivityDbm
	 *            the receive sensitivity threshold in dBm
	 */
	public void setRxSensitivityDbm(double rxSensitivityDbm) {
		this.rxSensitivityDbm = rxSensitivityDbm;
		this.rxSensitivityW = PropagationLossModel.dbmToW(rxSensitivityDbm);
	}

	/**
	 * Sets the receive sensitivity threshold.
	 * 
	 * @param rxSensitivityW
	 *            the receive sensitivity threshold in watt
	 */
	public void setRxSensitivityW(double rxSensitivityW) {
		this.rxSensitivityW = rxSensitivityW;
		this.rxSensitivityDbm = PropagationLossModel.wToDbm(rxSensitivityW);
	}

	/**
	 * Sets the transmit gain of the antenna in the {@link InterferenceHelper}.
	 * 
	 * @param gain
	 *            The transmit gain
	 */
	public void setTxGain(double gain) {
		this.interferenceHelper.setTxGainDbm(gain);
	}

	/**
	 * Sets the receive gain of the antenna in the {@link InterferenceHelper}.
	 * 
	 * @param gain
	 *            The receive gain
	 */
	public void setRxGain(double gain) {
		this.interferenceHelper.setRxGainDbm(gain);
	}
}