RINASim  October 2016
Documentation of framework for OMNeT++
MM_WFQ_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_WFQ_Out.h>
19 
20 namespace MM_WFQ_Out {
21 
23 
24 
26  rTkBit(0), sTkBit(0), maxTk(0), priority(0) {}
27 
29  hasTk(false), priority(0) {}
30 
31 Qinfo::Qinfo(const bool & _ht, const int & _pr) :
32  hasTk(_ht), priority(_pr) {}
33 
34 bool Qinfo::compare(const Qinfo & o) {
35  if(hasTk) {
36  if(o.hasTk) {
37  return priority < o.priority;
38  } else {
39  return false;
40  }
41  } else {
42  if(o.hasTk) {
43  return true;
44  } else {
45  return priority < o.priority;
46  }
47  }
48 }
49 
51  tk(0), w(0), c(QConfig()) {}
52 
53 void QData::addTk(const int & s) {
54  tk += s*c.rTkBit;
55  if(tk > c.maxTk) { tk = c.maxTk; }
56 }
57 void QData::remTk(const int & s) {
58  tk -= s*c.sTkBit;
59  if(tk < 0) { tk = 0; }
60 }
61 
62 Qinfo QData::getInfo(const int & nextS) {
63  return Qinfo(tk >= nextS * c.sTkBit, c.priority);
64 }
65 
66 
67 void MM_WFQ_Out::initialize() {
68  cXMLElement* Xml = NULL;
69  if (par("data").xmlValue() != NULL && par("data").xmlValue()->hasChildren()){
70  Xml = par("data").xmlValue();
71  } else { return; }
72 
73  cXMLElementList queues = Xml->getChildrenByTagName("queue");
74  for(auto queue : queues){
75  if (!queue->getAttribute("id")) { error("Error parsing WFQ_OUT Queue. Its ID is missing!"); }
76  std::string id = queue->getAttribute("id");
77  if (id=="") { error("Error parsing WFQ_OUT Queue. Queue ID cannot be empty!"); }
78 
79  QConfig c;
80 
81  if (!queue->getAttribute("priority")) { error("Error parsing WFQ_OUT Queue. Its Priority is missing!"); }
82  c.priority = atoi(queue->getAttribute("priority"));
83  if (c.priority<0) { error("Error parsing WFQ_OUT Queue. Queue Priority must be >=0!"); }
84 
85  if (!queue->getAttribute("rTkBit")) { error("Error parsing WFQ_OUT Queue. Its Received tokens per byte is missing!"); }
86  c.rTkBit = atoi(queue->getAttribute("rTkBit"));
87  if (c.rTkBit<=0) { error("Error parsing WFQ_OUT Queue. Queue Received tokens per byte must be >=0!"); }
88 
89  if (!queue->getAttribute("sTkBit")) { error("Error parsing WFQ_OUT Queue. Its Required tokens per byte is missing!"); }
90  c.sTkBit = atoi(queue->getAttribute("sTkBit"));
91  if (c.sTkBit<0) { error("Error parsing WFQ_OUT Queue. Queue Required tokens per byte must be >=0!"); }
92 
93  if (!queue->getAttribute("maxTk")) { error("Error parsing WFQ_OUT Queue. Its Max Tokens is missing!"); }
94  c.maxTk = atoi(queue->getAttribute("maxTk"));
95  if (c.maxTk<=0) { error("Error parsing WFQ_OUT Queue. Queue Max Tokens must be >=0!"); }
96 
97  queueName2Config[id] = c;
98  }
99 }
100 
101 MM_WFQ_Out::~MM_WFQ_Out(){}
102 
103 void MM_WFQ_Out::finish() {
104 
105 }
106 
107 void MM_WFQ_Out::pduInsertered(RMTQueue * q, RMTPort * p) {
108  queueData[q].w++;
109 }
110 
111 void MM_WFQ_Out::pduDropped(RMTQueue * q, const cPacket * s, RMTPort * p) {
112  queueData[q].w--;
113 }
114 
115 void MM_WFQ_Out::pduReleased(RMTQueue * q, RMTPort * p) {}
116 
117 void MM_WFQ_Out::queueCreated(RMTQueue * q, RMTPort * p) {
118  QData qd;
119  qd.c = queueName2Config[q->getName()];
120  queueData[q] = qd;
121  portQueues[p].push_back(q);
122 }
123 
124 RMTQueue * MM_WFQ_Out::getnextQueue(RMTPort * p) {
125  Qinfo ti;
126  RMTQueue * retQ = NULL;
127 
128  for(auto & q : portQueues[p]){
129  QData * qd = &queueData[q];
130 
131  if(qd->w > 0) {
132  int nextS = q->getFirstPDU()->getByteLength();
133  Qinfo i = qd->getInfo(nextS);
134  if(ti.compare(i)) {
135  ti = i;
136  retQ = q;
137  }
138  }
139  }
140 
141  if(retQ == NULL) {return NULL; }
142 
143  int nextS = retQ->getFirstPDU()->getByteLength();
144  queueData[retQ].w--;
145  queueData[retQ].remTk(nextS);
146  for(auto & q : portQueues[p]){
147  queueData[q].addTk(nextS);
148  }
149 
150  return retQ;
151 }
152 
153 simtime_t MM_WFQ_Out::getnextTime(RMTPort * p) {
154  return 0;
155 }
156 
157 }
void addTk(const int &s)
Definition: MM_WFQ_Out.cc:53
const cPacket * getFirstPDU() const
Definition: RMTQueue.cc:271
void remTk(const int &s)
Definition: MM_WFQ_Out.cc:57
Define_Module(MM_WFQ_Out)
Qinfo getInfo(const int &nextS)
Definition: MM_WFQ_Out.cc:62
bool compare(const Qinfo &o)
Definition: MM_WFQ_Out.cc:34