RINASim  October 2016
Documentation of framework for OMNeT++
MM_DQ_Out.cc
Go to the documentation of this file.
1 //
2 // Copyright © 2014 - 2015 PRISTINE Consortium (http://ict-pristine.eu)
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Lesser General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Lesser General Public License for more details.
13 //
14 // You should have received a copy of the GNU Lesser General Public License
15 // along with this program. If not, see http://www.gnu.org/licenses/.
16 //
17 
18 #include <MM_DQ_Out.h>
19 
20 namespace MM_DQ_Out {
21 
23 
24 UrgLimit::UrgLimit(double _limit, int _urg) {
25  limit = _limit;
26  urg = _urg;
27 }
28 
30  t = _t;
31 }
32 
34  id ="";
35  defPriority = 0;
36  rate = -1.0;
37 }
38 
39 QueueConfig::QueueConfig(string _id, int _defPriority){
40  id =_id;
41  defPriority = _defPriority;
42  rate = -1.0;
43 }
44 
46  count = 0;
47  lastUrgency = -1;
48 }
49 
50 
51 void MM_DQ_Out::initialize() {
52  defaultPriority = par("defPriority").longValue();
53  if(defaultPriority < 0) { error("Error at eDL_Out. defPriority must be >=0!"); }
54 
55  int rateUnit = par("rateUnit").longValue();
56  if(defaultPriority < 0) { error("Error at eDL_Out. defPriority must be >=0!"); }
57 
58  maxPriority = defaultPriority;
59 
60  cXMLElement* Xml = NULL;
61  if (par("data").xmlValue() != NULL && par("data").xmlValue()->hasChildren()){
62  Xml = par("data").xmlValue();
63  } else { return; }
64 
65  cXMLElementList queues = Xml->getChildrenByTagName("queue");
66  for(auto queue : queues){
67  if (!queue->getAttribute("id")) { error("Error parsing DQ_Out Queue. Its ID is missing!"); }
68  std::string id = queue->getAttribute("id");
69  if (id=="") { error("Error parsing DQ_Out Queue. Queue ID cannot be empty!"); }
70 
71  if (!queue->getAttribute("defPriority")) { error("Error parsing DQ_Out Queue. Its default Priority is missing!"); }
72  int defPriority = atoi(queue->getAttribute("defPriority"));
73  if (defPriority<0) { error("Error parsing DQ_Out Queue. Queue default Priority must be >=0!"); }
74  if(maxPriority<defPriority) { maxPriority = defPriority ; }
75 
76  QueueConfig q(id, defPriority);
77 
78  if(queue->getAttribute("rate")) {
79  double rate = atof(queue->getAttribute("rate"));
80  if(rate <= 0) { error("Error parsing DQ_Out Queue. Queue Rate cannot be <= 0"); }
81  rate *= rateUnit;
82 
83  q.rate = rate;
84 
85  cXMLElementList degradLists = queue->getChildrenByTagName("degradList");
86  for(auto degrad : degradLists){
87  if (!degrad->getAttribute("t")) { error("Error parsing degradList. Its t is missing!"); }
88  double t = atof(degrad->getAttribute("t"));
89  if (t<0) { error("Error parsing degradList. t cannot be <0!"); }
90 
91  DegradList dl(t);
92 
93  double sumProb = 0;
94 
95  cXMLElementList PPs = degrad->getChildrenByTagName("PP");
96 
97  if(PPs.size() <= 0) { error("Error parsing degradList. At least one PP must be defined!"); }
98  for(auto PP : PPs){
99  if(!PP->getAttribute("priority")) { error("Error parsing PP. priority must be defined!"); }
100  int priority = atoi(PP->getAttribute("priority"));
101  if(priority<0) { error("Error parsing PP. priority must be >=0!"); }
102  if(maxPriority<priority) { maxPriority = priority ; }
103 
104  if(!PP->getAttribute("probability")) { error("Error parsing PP. probability must be defined!"); }
105  double probability = atof(PP->getAttribute("probability"));
106  if(probability<=0 || probability>1) { error("Error parsing PP. probability must be in (0,1]!"); }
107 
108  sumProb += probability;
109 
110  dl.urgList.push_back( UrgLimit(sumProb, priority) );
111  }
112 
113  if(sumProb > 1) { error("Error parsing degradList. probability of PPs cannot surpass 1!"); }
114 
115  q.degradLists.push_back(dl);
116  }
117  }
118 
119  queuesConf[id] = q;
120  }
121 }
122 
123 MM_DQ_Out::~MM_DQ_Out(){}
124 
125 void MM_DQ_Out::finish() {
126  /*
127 cout << "MM_DQ_Out "<< endl;
128  for(auto pq : portQueues) {
129 
130  cout << "\tPort: "<<pq.first->getFullPath()<< endl;
131  for(RMTQueue *q : pq.second) {
132  QueueData * qd = &queueData[q];
133  cout << "\t\tQueue: "<< q->getName() << endl;
134  for(auto uc : qd->countUrgstats) {
135  cout << "\t\t\tUrgency: "<< uc.first << " (" << uc.second <<")" << endl;
136  }
137 
138  }
139  }
140 */
141 }
142 
143 void MM_DQ_Out::pduInsertered(RMTQueue * q, RMTPort * p) {
144  QueueData * qd = &queueData[q];
145  QueueConfig * qc = queueConf[q];
146  simtime_t now = simTime();
147 
148  //Push insert pdu
149  qd->count++;
150  qd->inTimes.push_back(now);
151 
152  if(!qc) {
153  //if queue not configured, urgency = default
154  qd->lastUrgency = maxPriority-defaultPriority;
155  } else if (qc->rate <= 0.0) {
156  //if queue not rate controled, urgency = queue by default
157  qd->lastUrgency = maxPriority-qc->defPriority;
158  } else {
159  //Get last out time
160  simtime_t lt = now;
161  while(!qd->outTimes.empty() && qd->outTimes.front() <= now) {
162  qd->outTimes.pop_front();
163  }
164  if(!qd->outTimes.empty()) { lt = qd->outTimes.back(); }
165 
166  simtime_t st = lt-now;
167 
168  //Get degradation list for current state
169  DegradList * dl = NULL;
170  for(DegradList & pdl : qc->degradLists) {
171  if(pdl.t > st) {
172  if(dl == NULL) { dl = &pdl; }
173  else if( dl->t < pdl.t) { dl = &pdl; }
174  }
175  }
176 
177  //Get urgency based on degradation list
178  if(dl == NULL) {
179  qd->lastUrgency = maxPriority-qc->defPriority;
180  } else {
181  int cPrio = qc->defPriority;
182  double r = uniform(0,1);
183 
184  for(UrgLimit & ul : dl->urgList) {
185  if(ul.limit < r) { cPrio = ul.urg; }
186  else { continue; }
187  }
188 
189  qd->lastUrgency = maxPriority-cPrio;
190  }
191 
192  //Compute and store out time
193  lt += q->getLastPDU()->getBitLength()/qc->rate;
194  qd->outTimes.push_back(lt);
195 
196  }
197 
198  //store queue urgency
199  qd->countUrg[qd->lastUrgency]++;
200  qd->countUrgstats[qd->lastUrgency]++;
201 }
202 
203 void MM_DQ_Out::pduDropped(RMTQueue * q, const cPacket * s, RMTPort * p) {
204  QueueData * qd = &queueData[q];
205 
206  if(qd->count > 0) {
207  qd->count--;
208  qd->inTimes.pop_back();
209  if(!qd->outTimes.empty()) { qd->outTimes.pop_back(); }
210  } else { error("PDU dropped from empty queue!??"); }
211 
212  if(qd->lastUrgency >=0) {
213  qd->countUrg[qd->lastUrgency]--;
214  qd->countUrgstats[qd->lastUrgency]--;
215  qd->lastUrgency = -1;
216  } else { error("Multiple PDUs dropped at same time!??"); }
217 }
218 
219 void MM_DQ_Out::pduReleased(RMTQueue * q, RMTPort * p) {}
220 
221 void MM_DQ_Out::queueCreated(RMTQueue * q, RMTPort * p) {
222  if(queuesConf.find(q->getName()) != queuesConf.end()) {
223  queueConf[q] = &queuesConf[q->getName()];
224  } else {
225  queueConf[q] = NULL;
226  }
227  queueData[q];
228 
229  portQueues[p].insert(q);
230 }
231 
232 RMTQueue * MM_DQ_Out::getnextQueue(RMTPort * p) {
233  int mpriority = -1;
234  simtime_t minT;
235  RMTQueue * ret = NULL;
236 
237  //select next queue : min priority (saved inverse), min inTime
238  for(RMTQueue *q : portQueues[p]) {
239  QueueData * qd = &queueData[q];
240  if(qd->count <= 0) { continue; }
241 
242  int qP = maxPriority;
243  for(auto & qpc : qd->countUrg) {
244  if(qpc.second > 0 && qpc.first < qP) { qP = qpc.first; }
245  }
246  if(mpriority < 0 || mpriority > qP) {
247  mpriority = qP;
248  minT = qd->inTimes.front();
249  ret = q;
250  } else if(mpriority == qP && minT > qd->inTimes.front()) {
251  minT = qd->inTimes.front();
252  ret = q;
253  }
254  }
255 
256  if(ret==NULL) { return NULL; }
257 
258  QueueData * qd = &queueData[ret];
259  qd->count--;
260  qd->inTimes.pop_front();
261  qd->countUrg[mpriority]--;
262 
263 
264  return ret;
265 }
266 
267 simtime_t MM_DQ_Out::getnextTime(RMTPort * p) {
268  return 0;
269 }
270 
271 }
map< int, int > countUrg
Definition: MM_DQ_Out.h:59
vector< UrgLimit > urgList
Definition: MM_DQ_Out.h:40
Define_Module(MM_DQ_Out)
vector< DegradList > degradLists
Definition: MM_DQ_Out.h:49
const cPacket * getLastPDU() const
Definition: RMTQueue.cc:276
list< simtime_t > inTimes
Definition: MM_DQ_Out.h:57
UrgLimit(double, int)
Definition: MM_DQ_Out.cc:24
map< int, int > countUrgstats
Definition: MM_DQ_Out.h:63
list< simtime_t > outTimes
Definition: MM_DQ_Out.h:58