485 lines
19 KiB
C++
485 lines
19 KiB
C++
/*
|
|
* File: WirelessConnectivityObserver.cc
|
|
* Author: thandreg
|
|
* Author: jgaebler
|
|
*
|
|
* Created on October 16, 2012, 1:30 PM
|
|
*/
|
|
#include "WirelessConnectivityObserver.h"
|
|
|
|
#include "NotificationInfo.h"
|
|
|
|
#include <FWMath.h>
|
|
|
|
#include "base/NotificationBoard.h"
|
|
#include "mobility/models/MovingMobilityBase.h"
|
|
#include "mobility/models/StationaryMobility.h"
|
|
|
|
#include <IRoutingTable.h>
|
|
#include <IInterfaceTable.h>
|
|
#include <IPvXAddressResolver.h>
|
|
#include <IPv4InterfaceData.h>
|
|
|
|
|
|
namespace ubeeme {
|
|
namespace moversight {
|
|
|
|
Define_Module(WirelessConnectivityObserver);
|
|
|
|
void
|
|
WirelessConnectivityObserver::initialize(int stage) {
|
|
|
|
if (stage == 2) {
|
|
|
|
nodeInfo.clear();
|
|
|
|
// extract topology into the cTopology object, then fill in
|
|
// isIPNode, rt and ift members of nodeInfo[]
|
|
extractTopology(topo, nodeInfo);
|
|
|
|
// assign addresses to IPv4 nodes, and also store result in nodeInfo[].address
|
|
assignAddresses(topo, nodeInfo);
|
|
|
|
// add default routes to hosts (nodes with a single attachment);
|
|
// also remember result in nodeInfo[].usesDefaultRoute
|
|
addDefaultRoutes(topo, nodeInfo);
|
|
|
|
// calculate shortest paths, and add corresponding static routes
|
|
fillRoutingTables(topo, nodeInfo);
|
|
|
|
// update display string
|
|
setDisplayString(topo, nodeInfo);
|
|
|
|
cc = dynamic_cast<IChannelControl *> (simulation.getModuleByPath("channelControl"));
|
|
if (!cc) {
|
|
throw cRuntimeError("Could not find ChannelControl module with name 'channelControl' in the toplevel network.");
|
|
}//End if
|
|
|
|
EV << "Initialising WirelessConnectivityObserver" << endl;
|
|
|
|
//initialize nodeList
|
|
topo.extractByProperty("node");
|
|
|
|
for (int i = 0; i < (topo.getNumNodes()); i++) {
|
|
|
|
//we are only interested in wireless nodes
|
|
if (topo.getNode(i)->getModule()->getSubmodule("wlan", 0)) {
|
|
|
|
std::string nodeName(topo.getNode(i)->getModule()->getFullName());
|
|
Node node(nodeName);
|
|
node.setRadioModule(topo.getNode(i)->getModule()->getSubmodule("wlan", 0)->getSubmodule("radio", 0));
|
|
|
|
MACAddress mac;
|
|
mac.setAddress(topo.getNode(i)->getModule()->getSubmodule("wlan", 0)->getSubmodule("mac", 0)->par("address").stringValue());
|
|
node.setMacAdress(mac);
|
|
|
|
int isMobil = topo.getNode(i)->getModule()->getSubmodule("mobility")->findPar("updateInterval");
|
|
if (isMobil != -1) {
|
|
node.setHasMobility(true);
|
|
}//end if
|
|
|
|
//setting event-listener to AccessPoints
|
|
if (topo.getNode(i)->getModule()->getSubmodule("relayUnit", 0) &&
|
|
topo.getNode(i)->getModule()->getSubmodule("notificationBoard", 0)) {
|
|
|
|
NotificationBoard * blackBoard = dynamic_cast<NotificationBoard *> (topo.getNode(i)->getModule()->getSubmodule("notificationBoard"));
|
|
if (!blackBoard) {
|
|
std::cerr << "Could not find NotificationBoard module with name 'notificationBoard' in AP-Node." << endl;
|
|
}//end if
|
|
else {
|
|
|
|
//categories for notifications
|
|
blackBoard->subscribe(this, NF_L2_AP_ASSOCIATED);
|
|
blackBoard->subscribe(this, NF_L2_AP_DISASSOCIATED);
|
|
}//end else
|
|
|
|
node.setIsAccessPoint(true);
|
|
|
|
}//end if
|
|
|
|
// Eventlistener to Notificationboard only for WirelessNodes
|
|
if (topo.getNode(i)->getModule()->getSubmodule("networkLayer", 0) &&
|
|
topo.getNode(i)->getModule()->getSubmodule("notificationBoard", 0)) {
|
|
|
|
NotificationBoard * blackBoard = dynamic_cast<NotificationBoard *> (topo.getNode(i)->getModule()->getSubmodule("notificationBoard"));
|
|
if (!blackBoard) {
|
|
std::cerr << "Could not find NotificationBoard module with name 'notificationBoard' in wlan-Node." << endl;
|
|
}
|
|
else {
|
|
//categories für notifications
|
|
blackBoard->subscribe(this, NF_L2_ASSOCIATED_NEWAP);
|
|
blackBoard->subscribe(this, NF_L2_BEACON_LOST);
|
|
blackBoard->subscribe(this, NF_L2_AP_ASSOCIATED);
|
|
|
|
}//End else
|
|
}
|
|
|
|
nodeList.push_back(node);
|
|
}
|
|
}
|
|
|
|
//init params
|
|
updateFrequency = par("updateFreq").doubleValue();
|
|
|
|
//starting Initialization2
|
|
selfTrigger = new cMessage("selfTrigger");
|
|
scheduleAt(simTime() + updateFrequency, selfTrigger);
|
|
}
|
|
}
|
|
|
|
void
|
|
WirelessConnectivityObserver::handleMessage(cMessage *msg) {
|
|
|
|
//we only handly selfTrigger messages
|
|
if (msg == selfTrigger) {
|
|
|
|
if (simTime() <= updateFrequency)
|
|
initalizeNodes();
|
|
|
|
else {
|
|
for (size_t i = 0; i < nodeList.size(); i++) {
|
|
updatePositons(i);
|
|
updateDistance(i);
|
|
timeLeft(i);
|
|
std::cerr << "Name: " << nodeList.at(i).getNodeName() << endl;
|
|
std::cerr << "verbundene Zeit: " << nodeList.at(i).getConnectedTime() << endl;
|
|
std::cerr << "verbleibene Zeit: " << nodeList.at(i).getTimeLeft() << endl;
|
|
std::cerr << "verbunden mit: " << nodeList.at(i).getConnectedWith() << endl;
|
|
std::cerr << "Speed: " << nodeList.at(i).getCurrentSpeed() << endl;
|
|
std::cerr << "num equal: " << nodeList.at(i).getNumEqualModules() << endl << endl;
|
|
}//End for
|
|
}//End else
|
|
|
|
scheduleAt(simTime() + updateFrequency, selfTrigger);
|
|
|
|
}//end if
|
|
}
|
|
|
|
void
|
|
WirelessConnectivityObserver::initalizeNodes() {
|
|
|
|
//initial the position of the nodes
|
|
for (size_t i = 0; i < nodeList.size(); i++) {
|
|
updatePositons(i);
|
|
}//end for
|
|
|
|
//initial the distance of the nodes
|
|
for (size_t i = 0; i < nodeList.size(); i++) {
|
|
|
|
Node & node = nodeList[i];
|
|
|
|
cModule * radioModule = node.getRadioModule();
|
|
if (radioModule != NULL) {
|
|
|
|
double transmissionPower = radioModule->par("transmitterPower");
|
|
double transmissionRange = calcDistFreeSpace(i, transmissionPower);
|
|
node.setTransmissionRange(transmissionRange);
|
|
|
|
for (size_t z = 0; z < nodeList.size(); z++) {
|
|
if (i != z && node.isAccessPoint() != nodeList[z].isAccessPoint()) {
|
|
|
|
double distance = node.getCurrentPosition().distance(nodeList[z].getCurrentPosition());
|
|
|
|
Distance temp(nodeList[z].getNodeName(), distance);
|
|
node.getNodeDistanceList().push_back(temp);
|
|
|
|
}//End if
|
|
}//end for
|
|
}//end if
|
|
}//end for
|
|
}
|
|
|
|
double
|
|
WirelessConnectivityObserver::calcDistFreeSpace(size_t nodesIndex, double transmissionPower) {
|
|
|
|
//the carrier frequency used
|
|
double carrierFrequency = getChannelControlPar("carrierFrequency");
|
|
|
|
//path loss coefficient
|
|
double alpha = getChannelControlPar("alpha");
|
|
|
|
double waveLength = (SPEED_OF_LIGHT / carrierFrequency);
|
|
|
|
//minimum power level to be able to physically receive a signal
|
|
double minReceivePower = FWMath::dBm2mW(double(nodeList.at(nodesIndex).getRadioModule()->par("sensitivity")));
|
|
|
|
double interfDistance = pow(waveLength * waveLength * transmissionPower /
|
|
(16.0 * M_PI * M_PI * minReceivePower), 1.0 / alpha);
|
|
|
|
return interfDistance;
|
|
}
|
|
|
|
void
|
|
WirelessConnectivityObserver::updatePositons(size_t i) {
|
|
|
|
Node & node = nodeList[i];
|
|
|
|
cModule * radio = node.getRadioModule();
|
|
|
|
if (radio != NULL) {
|
|
|
|
cModule* help = radio->getParentModule()->getParentModule()->getSubmodule("mobility", 0);
|
|
|
|
if (node.hasMobility()) {
|
|
|
|
//All mobilities inherit from same modules
|
|
MovingMobilityBase* mod = (MovingMobilityBase*) help;
|
|
node.setCurrentPosition(mod->getCurrentPosition());
|
|
node.setCurrentSpeed(mod->getCurrentSpeed() / 10);
|
|
|
|
}//end if
|
|
else {
|
|
|
|
// when there is no mobility
|
|
StationaryMobility* mod = (StationaryMobility*) help;
|
|
node.setCurrentPosition(mod->getCurrentPosition());
|
|
node.setCurrentSpeed(Coord::ZERO);
|
|
|
|
}//end else
|
|
}
|
|
}
|
|
|
|
void
|
|
WirelessConnectivityObserver::updateDistance(size_t nodeNum) {
|
|
|
|
Node & node = nodeList[nodeNum];
|
|
Node::DistanceList & distanceList = node.getNodeDistanceList();
|
|
|
|
for (size_t i = 0; i < distanceList.size(); i++) {
|
|
|
|
std::string neighbourNodeName = distanceList.at(i).getNodeName();
|
|
|
|
//found myself
|
|
if (node.getNodeName().compare(neighbourNodeName) == 0) continue;
|
|
|
|
//found position of neighbour
|
|
Coord neighbourPos;
|
|
for (size_t z = 0; z < nodeList.size(); z++) {
|
|
//node found?
|
|
|
|
if (nodeList[z].getNodeName().compare(neighbourNodeName) == 0) {
|
|
neighbourPos = nodeList[z].getCurrentPosition();
|
|
}//End if
|
|
}//End for
|
|
|
|
Coord selfPos = node.getCurrentPosition();
|
|
double distance = selfPos.distance(neighbourPos);
|
|
distanceList[i].setDistance(distance);
|
|
|
|
}//end for
|
|
}
|
|
|
|
void
|
|
WirelessConnectivityObserver::timeLeft(size_t nodeNum) {
|
|
|
|
bool connected = false;
|
|
Node & node = nodeList[nodeNum];
|
|
|
|
size_t neighbourNodeNum = 0;
|
|
|
|
node.setTimeLeft(0);
|
|
|
|
//test, to avoid errors
|
|
if (node.getNumEqualModules() == 0) {
|
|
return;
|
|
}//End if
|
|
|
|
if (node.getConnectedWith().compare("") != 0) {
|
|
connected = true;
|
|
}//End if
|
|
|
|
if (!connected) {
|
|
node.setConnectedTime(0);
|
|
}//End if
|
|
else {
|
|
//searching for connected Node
|
|
while (node.getConnectedWith().compare(nodeList.at(neighbourNodeNum).getNodeName()) != 0) {
|
|
neighbourNodeNum++;
|
|
}//End while
|
|
|
|
node.setConnectedTime(node.getConnectedTime() + updateFrequency);
|
|
|
|
Node connectedNode = nodeList.at(neighbourNodeNum);
|
|
|
|
double distance = node.getCurrentPosition().distance(connectedNode.getCurrentPosition());
|
|
|
|
Coord speed1 = connectedNode.getCurrentSpeed();
|
|
Coord speed2 = node.getCurrentSpeed();
|
|
|
|
Coord Pos = node.getCurrentPosition();
|
|
|
|
while (node.getTransmissionRange() >= distance) {
|
|
|
|
speed1 += connectedNode.getCurrentSpeed();
|
|
speed2 += node.getCurrentSpeed();
|
|
|
|
if (speed1 == speed2 && speed1 == Coord::ZERO) {
|
|
//std::cerr<<node.getNodeName()<<" ist undefiniert lange noch verbunden"<<endl;
|
|
return;
|
|
}
|
|
else {
|
|
Pos = Pos + speed1 + speed2;
|
|
distance = connectedNode.getCurrentPosition().distance(Pos);
|
|
}
|
|
|
|
node.setTimeLeft(node.getTimeLeft() + updateFrequency);
|
|
|
|
}//End while
|
|
|
|
//std::cerr<<node.getNodeName()<<" ist vorraussichtlich noch "<<node.getTimeLeft()<<" sec verbunden"<<endl;
|
|
}//End else
|
|
|
|
}
|
|
|
|
void
|
|
WirelessConnectivityObserver::receiveChangeNotification(int category, const cObject * details) {
|
|
|
|
size_t i = 0;
|
|
bool findObject = false;
|
|
std::string nodeName = nodeList.at(i).getNodeName();
|
|
|
|
// finds the the notification giving Object to assign wlan modul
|
|
// only for wireless Nodes
|
|
if (details) {
|
|
while (i < nodeList.size()) {
|
|
|
|
if (details->getFullPath().find(nodeName.c_str()) != details->getFullPath().npos) {
|
|
|
|
findObject = true;
|
|
// set Associated AccessPoint for Wireless Host
|
|
nodeList[i].setConnectedWith(nodeList[modulNumber].getNodeName());
|
|
// set Associatetd Wireless Host for AP
|
|
nodeList[modulNumber].setConnectedWith(nodeList[i].getNodeName());
|
|
break;
|
|
|
|
}//end if
|
|
|
|
i++;
|
|
|
|
}//End while
|
|
}//end if
|
|
|
|
if (!findObject) {
|
|
|
|
//only for wireless AccessPoints
|
|
|
|
const NotificationInfo * notiInfo = (NotificationInfo * const) details;
|
|
if (notiInfo) {
|
|
i = 0;
|
|
//compares MacAdresses of Nodes and finds the notification giving object
|
|
while (notiInfo->getApAddress() != nodeList.at(i).getMacAdress() && i < nodeList.size())
|
|
i++;
|
|
}
|
|
|
|
// APs changes notification first, so save the name of AP to associated AP with new associated WirelessNode
|
|
//number of the ap within the nodeList
|
|
modulNumber = i;
|
|
}//end else
|
|
|
|
switch (category) {
|
|
//emitted by Whost
|
|
case NF_L2_ASSOCIATED_NEWAP:
|
|
std::cerr << nodeList.at(i).getNodeName() << " associated with " << nodeList.at(modulNumber).getNodeName() << endl;
|
|
addRoute(i);
|
|
break;
|
|
// emitted by WHOST
|
|
case NF_L2_BEACON_LOST:
|
|
std::cerr << "wirelessNode " << nodeList.at(i).getNodeName() << " dissociated" << endl;
|
|
nodeList.at(i).setConnectedWith("");
|
|
break;
|
|
//emitted by AP
|
|
case NF_L2_AP_ASSOCIATED:
|
|
std::cerr << nodeList.at(i).getNodeName() << " associated" << endl;
|
|
break;
|
|
//probably did not work with this inet?!
|
|
case NF_L2_AP_DISASSOCIATED:
|
|
std::cerr << nodeList.at(i).getNodeName() << " dissociated" << endl;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void
|
|
WirelessConnectivityObserver::addRoute(size_t numNode) {
|
|
|
|
Node & node = nodeList[numNode]; //a wHost
|
|
std::string accessPointName = node.getConnectedWith();
|
|
|
|
//findet den node in der topologie
|
|
int findNode = 0;
|
|
while (findNode < topo.getNumNodes() &&
|
|
node.getNodeName().compare(topo.getNode(findNode)->getModule()->getFullName()) != 0) {
|
|
findNode++;
|
|
}//end while
|
|
|
|
cTopology::Node *destNode = topo.getNode(findNode);
|
|
|
|
IPv4Address destAddr = nodeInfo[findNode].address;
|
|
std::string destModName = destNode->getModule()->getFullName();
|
|
|
|
//findet den passenden AccessPoint in topo
|
|
int findAP = 0;
|
|
while (findAP < topo.getNumNodes()) {
|
|
if (accessPointName.compare(topo.getNode(findAP)->getModule()->getFullPath()) == 0) {
|
|
destNode = topo.getNode(findAP);
|
|
}//End if
|
|
findAP++;
|
|
}
|
|
|
|
// calculate shortest paths from everywhere towards destNode
|
|
topo.calculateUnweightedSingleShortestPathsTo(destNode);
|
|
|
|
// add route (with host=destNode) to every routing table in the network
|
|
// (excepting nodes with only one interface -- there we'll set up a default route)
|
|
for (int j = 0; j < topo.getNumNodes(); j++) {
|
|
if (findNode == j) continue;
|
|
if (!nodeInfo[j].isIPNode)
|
|
continue;
|
|
|
|
cTopology::Node *atNode = topo.getNode(j);
|
|
|
|
if (atNode->getNumPaths() == 0)
|
|
continue; // not connected
|
|
|
|
if (nodeInfo[j].usesDefaultRoute)
|
|
continue; // already added default route here
|
|
|
|
IPv4Address atAddr = nodeInfo[j].address;
|
|
|
|
IInterfaceTable *ift = nodeInfo[j].ift;
|
|
|
|
int outputGateId = atNode->getPath(0)->getLocalGate()->getId();
|
|
InterfaceEntry *ie = ift->getInterfaceByNodeOutputGateId(outputGateId);
|
|
if (!ie)
|
|
error("%s has no interface for output gate id %d", ift->getFullPath().c_str(), outputGateId);
|
|
|
|
EV << " from " << atNode->getModule()->getFullName() << "=" << IPv4Address(atAddr);
|
|
EV << " towards " << destModName << "=" << IPv4Address(destAddr) << " interface " << ie->getName() << endl;
|
|
|
|
// delete old route
|
|
IRoutingTable *rt = nodeInfo[j].rt;
|
|
int i = rt->getNumRoutes();
|
|
for (; i > 0; i--) {
|
|
IPv4Route* x = rt->getRoute(i - 1);
|
|
if (x->getDestination() == destAddr)
|
|
rt->deleteRoute(x);
|
|
}
|
|
|
|
// add new route
|
|
IPv4Route *e = new IPv4Route();
|
|
e->setDestination(destAddr);
|
|
e->setNetmask(IPv4Address(255, 255, 255, 255)); // full match needed
|
|
e->setInterface(ie);
|
|
e->setSource(IPv4Route::MANUAL);
|
|
rt->addRoute(e);
|
|
|
|
}
|
|
}
|
|
|
|
cPar &
|
|
WirelessConnectivityObserver::getChannelControlPar(const char *parName) {
|
|
return dynamic_cast<cModule *> (cc)->par(parName);
|
|
}
|
|
|
|
} // end namespace moversight
|
|
} // end namespace ubeeme
|