Alex Bikfalvi
SimStream Documentation
Link.cpp
00001 #include "Headers.h" 00002 #include "Link.h" 00003 #include "EventLinkQueue.h" 00004 #include "EventLinkDelay.h" 00005 #include "Console.h" 00006 00007 #define LINK_NODE_OUT(in) (in ^ 1) 00008 00009 CLink::CLink( 00010 __uint32 id, 00011 CSimHandler* sim, 00012 __uint32 queue, 00013 __bitrate bandwidth0, 00014 __bitrate bandwidth1, 00015 __time delay0, 00016 __time delay1 00017 ) : CObject(sim) 00018 { 00019 this->id = id; 00020 00021 assert(bandwidth); 00022 this->bandwidth[0] = bandwidth0; 00023 this->bandwidth[1] = bandwidth1; 00024 this->delay[0] = delay0; 00025 this->delay[1] = delay1; 00026 00027 this->nodes[0] = NULL; 00028 this->nodes[1] = NULL; 00029 00030 this->nodeEntries[0] = 0; 00031 this->nodeEntries[1] = 0; 00032 00033 // Low priority queues 00034 this->queues[0][0] = new CLinkQueue(queue); 00035 this->queues[0][1] = new CLinkQueue(queue); 00036 00037 // High priority queues 00038 this->queues[1][0] = new CLinkQueue(queue); 00039 this->queues[1][1] = new CLinkQueue(queue); 00040 00041 this->currentNode = 0; 00042 00043 // Utilization meter 00044 this->meterTime[0] = 0; 00045 this->meterTime[1] = 0; 00046 this->meterUtil[0] = 0; 00047 this->meterUtil[1] = 0; 00048 00049 // Statistics 00050 this->statUtil[0][0] = 0; 00051 this->statUtil[0][1] = 0; 00052 this->statUtil[1][0] = 0; 00053 this->statUtil[1][1] = 0; 00054 00055 this->statQueue[0][0] = 0; 00056 this->statQueue[0][1] = 0; 00057 this->statQueue[1][0] = 0; 00058 this->statQueue[1][1] = 0; 00059 00060 this->statQueueLast[0][0] = 0; 00061 this->statQueueLast[0][1] = 0; 00062 this->statQueueLast[1][0] = 0; 00063 this->statQueueLast[1][1] = 0; 00064 00065 this->statPackets[0][0] = 0; 00066 this->statPackets[0][1] = 0; 00067 this->statPackets[1][0] = 0; 00068 this->statPackets[1][1] = 0; 00069 00070 this->statBits[0][0] = 0; 00071 this->statBits[0][1] = 0; 00072 this->statBits[1][0] = 0; 00073 this->statBits[1][1] = 0; 00074 00075 this->statDiscard[0][0] = 0; 00076 this->statDiscard[0][1] = 0; 00077 this->statDiscard[1][0] = 0; 00078 this->statDiscard[1][1] = 0; 00079 } 00080 00081 CLink::~CLink() 00082 { 00083 delete this->queues[0][0]; 00084 delete this->queues[0][1]; 00085 delete this->queues[1][0]; 00086 delete this->queues[1][1]; 00087 } 00088 00089 double CLink::meterSmoothFactor = 0.9; 00090 00091 __uint32 CLink::AddNode(CObject* node, __uint32 entry) 00092 { 00093 assert(node); 00094 assert(this->currentNode < 2); 00095 00096 this->nodes[this->currentNode] = node; 00097 this->nodeEntries[this->currentNode] = entry; 00098 00099 this->currentNode++; 00100 00101 return this->currentNode-1; 00102 } 00103 00104 ENetworkCode CLink::Recv(CObject* sender, __uint32 entry, CPacket* packet) 00105 { 00106 assert(sender); 00107 assert(packet); 00108 assert((0 == entry) || (1 == entry)); 00109 assert(this->nodes[entry] == sender); 00110 00111 __byte tos = packet->Tos(); 00112 00113 #ifdef LOG_LINK 00114 CConsole::SetColor(CConsole::LIGHT_YELLOW); 00115 printf("\n%10.6lf : LINK_%x RECV entry=%u size=%u tos=%u queue=%u/%u", this->sim->Time(), this->id, entry, packet->Size(), tos, this->queues[tos][entry]->Packets(), this->queues[tos][entry]->Size()); 00116 CConsole::SetColor(CConsole::LIGHT_GRAY); 00117 #endif 00118 00119 // Stat : packets 00120 this->statPackets[tos][entry]++; 00121 00122 // If the queue is full discard the message 00123 if(this->queues[tos][entry]->IsFull()) 00124 { 00125 #ifdef LOG_LINK 00126 CConsole::SetColor(CConsole::LIGHT_YELLOW); 00127 printf("\n%10.6lf : LINK_%x DISCARD tos=%u", this->sim->Time(), this->id, tos); 00128 CConsole::SetColor(CConsole::LIGHT_GRAY); 00129 #endif 00130 00131 // Verify that high priority packets are not discarded 00132 assert(tos == CPacket::PACKET_TOS_LOW); 00133 00134 // Stat : discarded packets 00135 this->statDiscard[tos][entry]++; 00136 00137 packet->Delete(); 00138 delete packet; 00139 return NETWORK_FAIL; 00140 } 00141 00142 // If all queues are empty, schedule a link event now to transmit the message 00143 if(this->queues[0][entry]->IsEmpty() && this->queues[1][entry]->IsEmpty()) 00144 { 00145 #ifdef LOG_LINK 00146 CConsole::SetColor(CConsole::LIGHT_YELLOW); 00147 printf("\n%10.6lf : LINK_%x START SEND size=%u tos=%u bw=%lf delay=%lf (forw=%lf tran=%lf)", this->sim->Time(), this->id, packet->Size(), tos, this->bandwidth[entry], this->delay[entry] + (packet->Size() / this->bandwidth[entry]), this->delay[entry], (packet->Size() / this->bandwidth[entry])); 00148 CConsole::SetColor(CConsole::LIGHT_GRAY); 00149 #endif 00150 __time delay = (packet->Size() + 1) / this->bandwidth[entry]; 00151 00152 CEventLinkQueue* evt = new CEventLinkQueue(this, entry, packet); 00153 this->sim->ScheduleEventAfter( 00154 delay, 00155 evt 00156 ); 00157 00158 // Stat : link utlization 00159 this->statUtil[tos][entry] += packet->Size() / this->bandwidth[entry]; 00160 00161 // Stat : data 00162 this->statBits[tos][entry] += packet->Size(); 00163 00164 // Utilization meter 00165 this->meterUtil[entry] = CLink::meterSmoothFactor * packet->Size() / (this->sim->Time() + delay - this->meterTime[entry]) + 00166 (1 - CLink::meterSmoothFactor) * this->meterUtil[entry]; 00167 this->meterTime[entry] = this->sim->Time() + delay; 00168 } 00169 #ifdef LOG_LINK 00170 else 00171 { 00172 CConsole::SetColor(CConsole::LIGHT_YELLOW); 00173 printf("\n%10.6lf : LINK_%x ENQUEUE", this->sim->Time(), this->id); 00174 CConsole::SetColor(CConsole::LIGHT_GRAY); 00175 } 00176 #endif 00177 00178 // Stat : queue 00179 this->statQueue[tos][entry] += this->queues[tos][entry]->Packets() * (this->sim->Time() - this->statQueueLast[tos][entry]); 00180 this->statQueueLast[tos][entry] = this->sim->Time(); 00181 00182 // Add the message to the queue 00183 this->queues[tos][entry]->Add(this->sim->Time(), packet); 00184 00185 return NETWORK_SUCCESS; 00186 } 00187 00188 void CLink::Delay(__uint32 entry, CPacket* packet) 00189 { 00190 assert(packet); 00191 00192 __byte tos = packet->Tos(); 00193 00194 assert(this->queues[tos][entry]->First() == packet); 00195 00196 // Stat : queue 00197 this->statQueue[tos][entry] += this->queues[tos][entry]->Packets() * (this->sim->Time() - this->statQueueLast[tos][entry]); 00198 this->statQueueLast[tos][entry] = this->sim->Time(); 00199 00200 // Remove packet from the queue 00201 this->queues[tos][entry]->Remove(); 00202 00203 #ifdef LOG_LINK 00204 CConsole::SetColor(CConsole::LIGHT_YELLOW); 00205 printf("\n%10.6lf : LINK_%x DELAY SEND size=%u tos=%u", this->sim->Time(), this->id, packet->Size(), tos); 00206 CConsole::SetColor(CConsole::LIGHT_GRAY); 00207 #endif 00208 00209 // Delay the packet 00210 CEventLinkDelay* evt = new CEventLinkDelay(this, entry, packet); 00211 00212 this->sim->ScheduleEventAfter( 00213 this->delay[entry], 00214 evt); 00215 00216 // If the queue is not empty, process the next packet starting with the high priority queue 00217 for(__byte tos = CPacket::PACKET_TOS_HIGH; tos <= CPacket::PACKET_TOS_LOW; tos++) 00218 { 00219 if(!this->queues[tos][entry]->IsEmpty()) 00220 { 00221 assert(this->queues[tos][entry]->First()); 00222 00223 CPacket* packet = this->queues[tos][entry]->First(); 00224 00225 assert(packet->Tos() == tos); 00226 00227 #ifdef LOG_LINK 00228 CConsole::SetColor(CConsole::LIGHT_YELLOW); 00229 printf("\n%10.6lf : LINK_%x START SEND size=%u tos=%u bw=%lf delay=%lf (forw=%lf tran=%lf)", this->sim->Time(), this->id, packet->Size(), tos, this->bandwidth[entry], this->delay[entry] + (packet->Size() / this->bandwidth[entry]), this->delay[entry], (packet->Size() / this->bandwidth[entry])); 00230 CConsole::SetColor(CConsole::LIGHT_GRAY); 00231 #endif 00232 __time delay = (packet->Size() + 1) / this->bandwidth[entry]; 00233 00234 00235 CEventLinkQueue* evt = new CEventLinkQueue(this, entry, packet); 00236 00237 this->sim->ScheduleEventAfter( 00238 delay, 00239 evt 00240 ); 00241 00242 // Stat : link utlization 00243 this->statUtil[tos][entry] += packet->Size() / this->bandwidth[entry]; 00244 00245 // Stat : data 00246 this->statBits[tos][entry] += packet->Size(); 00247 00248 // Utilization meter 00249 this->meterUtil[entry] = CLink::meterSmoothFactor * packet->Size() / (this->sim->Time() + delay - this->meterTime[entry]) + 00250 (1 - CLink::meterSmoothFactor) * this->meterUtil[entry]; 00251 this->meterTime[entry] = this->sim->Time() + delay; 00252 00253 // If one packet is transmitted, stop the loop 00254 break; 00255 } 00256 } 00257 } 00258 00259 void CLink::Send(__uint32 entry, CPacket* packet) 00260 { 00261 __uint32 out = LINK_NODE_OUT(entry); 00262 00263 #ifdef LOG_LINK 00264 CConsole::SetColor(CConsole::LIGHT_YELLOW); 00265 printf("\n%10.6lf : LINK_%x FINISH SEND entry=%u size=%u tos=%u", this->sim->Time(), this->id, out, packet->Size(), packet->Tos()); 00266 CConsole::SetColor(CConsole::LIGHT_GRAY); 00267 #endif 00268 00269 // Call receive function of the destination node 00270 this->nodes[out]->Recv(this, this->nodeEntries[out], packet); 00271 } 00272 00273 __bitrate CLink::MeterUtil(__uint8 entry) 00274 { 00275 return this->meterUtil[entry]; 00276 } 00277 00278 void CLink::Finalize() 00279 { 00280 this->statUtil[0][0] /= this->sim->Time(); 00281 this->statUtil[0][1] /= this->sim->Time(); 00282 this->statUtil[1][0] /= this->sim->Time(); 00283 this->statUtil[1][1] /= this->sim->Time(); 00284 00285 this->statQueue[0][0] += this->queues[0][0]->Packets() * (this->sim->Time() - this->statQueueLast[0][0]); 00286 this->statQueue[0][1] += this->queues[0][1]->Packets() * (this->sim->Time() - this->statQueueLast[0][1]); 00287 this->statQueue[1][0] += this->queues[1][0]->Packets() * (this->sim->Time() - this->statQueueLast[1][0]); 00288 this->statQueue[1][1] += this->queues[1][1]->Packets() * (this->sim->Time() - this->statQueueLast[1][1]); 00289 00290 this->statQueue[0][0] /= this->sim->Time(); 00291 this->statQueue[0][1] /= this->sim->Time(); 00292 this->statQueue[1][0] /= this->sim->Time(); 00293 this->statQueue[1][1] /= this->sim->Time(); 00294 }
Last updated: February 8, 2011