RINASim  October 2016
Documentation of framework for OMNeT++
MM_psDQ_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_psDQ_Out.h>
19 
20 namespace MM_psDQ_Out {
21 
23 
24 UrgProb::UrgProb(double _prob, int _urg) {
25  prob = _prob;
26  urg = _urg;
27 }
28 
30  start = _s;
31 }
32 
34  id ="";
35  defPriority = 0;
36  rate = 0;
37 }
38 
39 QueueConfig::QueueConfig(string _id, int _defPriority){
40  id =_id;
41  defPriority = _defPriority;
42  rate = 0;
43 }
44 
46  count = 0;
47  lastUrgency = -1;
48 }
49 
50 
51 void MM_psDQ_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 
86  cXMLElementList degradLists = queue->getChildrenByTagName("degradList");
87  for(auto degrad : degradLists){
88  if (!degrad->getAttribute("s")) { error("Error parsing degradList. Its t is missing!"); }
89  int s = atoi(degrad->getAttribute("s"));
90  if (s<0) { error("Error parsing degradList. t cannot be <0!"); }
91 
92  DegradList dl(s);
93  double sumProb = 0;
94  cXMLElementList PPs = degrad->getChildrenByTagName("PP");
95 
96  if(PPs.size() <= 0) { error("Error parsing degradList. At least one PP must be defined!"); }
97  for(auto PP : PPs){
98  if(!PP->getAttribute("priority")) { error("Error parsing PP. priority must be defined!"); }
99  int priority = atoi(PP->getAttribute("priority"));
100  if(priority<0) { error("Error parsing PP. priority must be >=0!"); }
101  if(maxPriority<priority) { maxPriority = priority ; }
102 
103  if(!PP->getAttribute("probability")) { error("Error parsing PP. probability must be defined!"); }
104  double probability = atof(PP->getAttribute("probability"));
105  if(probability<=0 || probability>1) { error("Error parsing PP. probability must be in (0,1]!"); }
106 
107  sumProb += probability;
108 
109  dl.urgList.push_back( UrgProb(sumProb, priority) );
110  }
111 
112  if(sumProb > 1) { error("Error parsing degradList. probability of PPs cannot surpass 1!"); }
113 
114  q.degradLists.push_back(dl);
115  }
116 
117  queuesConf[id] = q;
118  }
119 }
120 
121 MM_psDQ_Out::~MM_psDQ_Out(){}
122 
123 void MM_psDQ_Out::finish() {
124  /*
125 cout << "MM_psDQ_Out "<< endl;
126  for(auto pq : portQueues) {
127 
128  cout << "\tPort: "<<pq.first->getFullPath()<< endl;
129  for(RMTQueue *q : pq.second) {
130  QueueData * qd = &queueData[q];
131  cout << "\t\tQueue: "<< q->getName() << endl;
132  for(auto uc : qd->countUrgstats) {
133  cout << "\t\t\tUrgency: "<< uc.first << " (" << uc.second <<")" << endl;
134  }
135 
136  }
137  }
138 */
139 }
140 
141 void MM_psDQ_Out::pduInsertered(RMTQueue * q, RMTPort * p) {
142  QueueData * qd = &queueData[q];
143  QueueConfig * qc = queueConf[q];
144  simtime_t t = simTime();
145 
146  //Push insert pdu
147  qd->count++;
148  int pC = ++portCount[p];
149 
150  if (qc->rate > 0.0) {
151  while(qd->cOutTimes.front() <= t ) { qd->cOutTimes.pop_front(); }
152  if(!qd->cOutTimes.empty()) { t = qd->cOutTimes.front(); }
153 
154  qd->cOutTimes.push_back(t + exponential(q->getLastPDU()->getBitLength()/qc->rate));
155  }
156 
157  if(!qc) {
158  //if queue not configured, urgency = default
159  qd->lastUrgency = maxPriority-defaultPriority;
160  } else {
161  //Get degradation list for current state
162  DegradList * dl = NULL;
163  for(DegradList & pdl : qc->degradLists) {
164  if(pdl.start > pC) {
165  if(dl == NULL) { dl = &pdl; }
166  else if( dl->start < pdl.start) { dl = &pdl; }
167  }
168  }
169 
170  //Get urgency based on degradation list
171  if(dl == NULL) {
172  qd->lastUrgency = maxPriority-qc->defPriority;
173  } else {
174  int cPrio = qc->defPriority;
175  double r = uniform(0,1);
176 
177  for(UrgProb & ul : dl->urgList) {
178  if(ul.prob < r) { cPrio = ul.urg; }
179  else { continue; }
180  }
181 
182  qd->lastUrgency = maxPriority-cPrio;
183  }
184  }
185 
186  //store queue urgency
187  qd->countUrg[qd->lastUrgency]++;
188  qd->countUrgstats[qd->lastUrgency]++;
189 }
190 
191 void MM_psDQ_Out::pduDropped(RMTQueue * q, const cPacket * s, RMTPort * p) {
192  QueueData * qd = &queueData[q];
193  portCount[p]--;
194 
195  if(qd->count > 0) {
196  qd->count--;
197  if(!qd->cOutTimes.empty()) { qd->cOutTimes.pop_back(); }
198  } else { error("PDU dropped from empty queue!??"); }
199 
200  if(qd->lastUrgency >=0) {
201  qd->countUrg[qd->lastUrgency]--;
202  qd->countUrgstats[qd->lastUrgency]--;
203  qd->lastUrgency = -1;
204  } else { error("Multiple PDUs dropped at same time!??"); }
205 }
206 
207 void MM_psDQ_Out::pduReleased(RMTQueue * q, RMTPort * p) {}
208 
209 void MM_psDQ_Out::queueCreated(RMTQueue * q, RMTPort * p) {
210  if(queuesConf.find(q->getName()) != queuesConf.end()) {
211  queueConf[q] = &queuesConf[q->getName()];
212  } else {
213  queueConf[q] = NULL;
214  }
215  queueData[q];
216 
217  portQueues[p].insert(q);
218 }
219 
220 RMTQueue * MM_psDQ_Out::getnextQueue(RMTPort * p) {
221  int mpriority = -1;
222  bool shaped = false;
223  simtime_t minT, now=simTime();
224  RMTQueue * ret = NULL;
225 
226  //select next queue : min priority (saved inverse), min inTime
227  for(RMTQueue *q : portQueues[p]) {
228  QueueData * qd = &queueData[q];
229  if(qd->count <= 0) { continue; }
230 
231  int qP = maxPriority;
232  for(auto & qpc : qd->countUrg) {
233  if(qpc.second > 0 && qpc.first < qP) { qP = qpc.first; }
234  }
235 
236  bool qShaped = ((int)qd->cOutTimes.size() < qd->count)
237  || (qd->cOutTimes.front() <= now);
238 
239  if(qShaped) {
240  if(!shaped) {
241  shaped = true;
242  mpriority = qP;
243  minT = qd->cOutTimes.front();
244  ret = q;
245  } else if(mpriority < 0 || mpriority > qP) {
246  mpriority = qP;
247  minT = qd->cOutTimes.front();
248  ret = q;
249  } else if(mpriority == qP && minT > qd->cOutTimes.front()) {
250  minT = qd->cOutTimes.front();
251  ret = q;
252  }
253  } else if(!shaped) {
254  if(mpriority < 0 || mpriority > qP) {
255  mpriority = qP;
256  minT = qd->cOutTimes.front();
257  ret = q;
258  } else if(mpriority == qP && minT > qd->cOutTimes.front()) {
259  minT = qd->cOutTimes.front();
260  ret = q;
261  }
262  }
263  }
264 
265  if(ret==NULL) { return NULL; }
266 
267  QueueData * qd = &queueData[ret];
268  qd->count--;
269  qd->countUrg[mpriority]--;
270  portCount[p]--;
271 
272 
273  return ret;
274 }
275 
276 simtime_t MM_psDQ_Out::getnextTime(RMTPort * p) {
277  return 0;
278 }
279 
280 }
vector< DegradList > degradLists
Definition: MM_psDQ_Out.h:49
const cPacket * getLastPDU() const
Definition: RMTQueue.cc:276
UrgProb(double, int)
Definition: MM_psDQ_Out.cc:24
map< int, int > countUrg
Definition: MM_psDQ_Out.h:58
list< simtime_t > cOutTimes
Definition: MM_psDQ_Out.h:57
Define_Module(MM_psDQ_Out)
map< int, int > countUrgstats
Definition: MM_psDQ_Out.h:62
vector< UrgProb > urgList
Definition: MM_psDQ_Out.h:40