--- a
+++ b/src/policies/DIF/Routing/DomainRouting/LS/LS.cc
@@ -0,0 +1,262 @@
+/*
+ * LS.cc
+ *
+ * Created on: Mar 23, 2015
+ * Author: gaixas1
+ */
+
+#include "DomainRouting/LS/LS.h"
+#include "DomainRouting/Routing.h"
+
+namespace DMRnmsLS {
+
+using namespace DMRnms;
+using namespace std;
+
+
+
+LSUpdate::LSUpdate(const Address &_addr, const string &_domain)
+ :RoutingUpdate(_addr, _domain){}
+
+
+void LSUpdate::addEntry(const std::string & _addr, linksU _neig) {
+ entries[_addr] = _neig;
+}
+void LSUpdate::setEntries(linksSt _entries) {
+ entries = _entries;
+}
+
+linksStIt LSUpdate::entriesBegin() {
+ return entries.begin();
+}
+
+linksStIt LSUpdate::entriesEnd() {
+ return entries.end();
+}
+
+
+LS::LS(Routing * parent, const Address &_nAddr, const string &_domain, const string &_addr)
+ :rModule(parent, _nAddr, _domain, _addr) {
+ scheduledUpdate = false;
+ secId = 1;
+}
+
+bool LS::processUpdate(RoutingUpdate * update){
+ // Cast update to known type
+ LSUpdate * up = dynamic_cast<LSUpdate*>(update);
+ if(up == NULL) { return false; }
+
+ for(linksStIt it = up->entriesBegin(); it != up->entriesEnd(); it++){
+ string node = it->first;
+ if(netState[node].sId < it->second.sId){
+ netState[node] = it->second;
+ changed.insert(node);
+ }
+ }
+
+ if(! changed.empty()) {
+ scheduleUpdate();
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void LS::addFlow(const Address &_nAddr, const std::string &_addr, const unsigned short &_metric){
+ nei[_nAddr] = _metric;
+ neigTable[_addr] = _nAddr;
+
+ changed.insert(myAddr);
+ secId++;
+
+ linksU * myEntry = &(netState[myAddr]);
+ myEntry->sId = secId;
+ myEntry->links[_addr] = _metric;
+
+ scheduleUpdate();
+}
+
+void LS::removeFlow(const Address &_nAddr, const std::string &_addr){
+ nei.erase(_nAddr);
+ neigTable.erase(_addr);
+
+ changed.insert(myAddr);
+ secId++;
+
+ linksU * myEntry = &(netState[myAddr]);
+ myEntry->sId = secId;
+ myEntry->links.erase(_addr);
+
+ scheduleUpdate();
+}
+
+void LS::addAddr(const std::string &_addr){
+ myAddrSet.insert(_addr);
+
+ secId++;
+
+ linksU * myEntry = &(netState[myAddr]);
+ myEntry->sId = secId;
+ myEntry->links[_addr] = 0;
+
+ scheduleUpdate();
+}
+
+void LS::removeAddr(const std::string &_addr){
+ myAddrSet.erase(_addr);
+
+ secId++;
+
+ linksU * myEntry = &(netState[myAddr]);
+ myEntry->sId = secId;
+ myEntry->links.erase(_addr);
+
+ scheduleUpdate();
+}
+
+void LS::setInfMetric(const unsigned short &inf){}
+
+dmNxt LS::getChanges(){
+ dmNxt ret(domain);
+
+ TreeNode t = constructTree();
+ for(TreeNodeIt it = t.chl.begin(); it != t.chl.end(); it++){
+ ret.entries[(*it)->addr] = neigTable[(*it)->addr];
+ addRecursive(ret.entries, neigTable[(*it)->addr], *it);
+ }
+
+ s2A tmp = ret.entries;
+
+ for(s2AIt tIt = currentTable.begin(); tIt != currentTable.end(); tIt++){
+ if(ret.entries[tIt->first] == tIt->second){
+ ret.entries.erase(tIt->first);
+ }
+ }
+
+ currentTable = tmp;
+
+ return ret;
+}
+
+dmNxt LS::getAll() {
+ dmNxt ret(domain);
+
+ TreeNode t = constructTree();
+ for(TreeNodeIt it = t.chl.begin(); it != t.chl.end(); it++){
+ ret.entries[(*it)->addr] = neigTable[(*it)->addr];
+ addRecursive(ret.entries, neigTable[(*it)->addr], *it);
+ }
+
+ currentTable = ret.entries;
+ return ret;
+}
+
+void LS::handleMessage(cMessage *msg){
+ if(msg->isSelfMessage()){
+ //get Changes
+ linksSt _entries = getChangedEntries ();
+
+ //iterate all Neighbour
+ for(neighMetricIt itN = nei.begin(); itN != nei.end(); itN++){
+ //New Update to Neighbour
+ LSUpdate * update = new LSUpdate(itN->first, domain);
+
+ //Populate the update
+ update->setEntries(_entries);
+
+ parent->chSendUpdate(update);
+ }
+
+ changed.clear();
+ scheduledUpdate = false;
+ }
+ delete msg;
+}
+
+
+void LS::scheduleUpdate(){
+ if(!scheduledUpdate){
+ scheduledUpdate = true;
+ scheduleAt(1, new cMessage("Time2Update"));
+ }
+}
+
+
+
+linksSt LS::getChangedEntries () {
+ linksSt ret;
+ for(sSetIt it = changed.begin(); it != changed.end(); it++){
+ ret[*it] = netState[*it];
+ }
+ return ret;
+}
+
+
+TreeNode LS::constructTree() {
+ TreeNode t(myAddr, 0);
+ s2m added;
+ added[myAddr] = 0;
+
+ wMap waiting;
+ s2m * links = &(netState[myAddr].links);
+ for(s2mIt it = links->begin(); it !=links->end(); it++){
+ waiting[it->first] = psT(&t, it->second);
+ }
+
+
+ while(!waiting.empty()){
+ unsigned short min = UINT16_MAX;
+ sList mins;
+
+ for (wMapIt it = waiting.begin(); it != waiting.end(); it++){
+ if(it->second.metric < min){
+ min = it->second.metric;
+ mins.clear();
+ }
+ if(it->second.metric == min){
+ mins.push_back(it->first);
+ }
+ }
+
+ while(!mins.empty()){
+ string addr = mins.back();
+ mins.pop_back();
+
+ psT ps = waiting[addr];
+ waiting.erase(addr);
+
+ TreeNode * nt = new TreeNode(addr, ps.metric);
+ ps.p->chl.insert(nt);
+
+ added[addr] = ps.metric;
+
+ links = &(netState[addr].links);
+
+ for(s2mIt it = links->begin(); it !=links->end(); it++){
+ string daddr = it->first;
+ if(added.find(daddr) == added.end()){
+ wMapIt eI = waiting.find(daddr);
+ if(eI == waiting.end()){
+ waiting[daddr] = psT(nt, ps.metric + it->second);
+ } else if(eI->second.metric > ps.metric + it->second){
+ eI->second.metric = ps.metric + it->second;
+ eI->second.p = nt;
+ }
+ }
+ }
+ }
+ }
+
+ return t;
+}
+
+void LS::addRecursive(s2A &ret, const Address &next, TreeNode * t) {
+ for(TreeNodeIt it = t->chl.begin(); it != t->chl.end(); it++){
+ ret[(*it)->addr] = next;
+ addRecursive(ret, next, *it);
+ }
+}
+
+
+
+} /* namespace DomainRouting */