NetSim Source Code Help v14.4
All 13 Components
 
Loading...
Searching...
No Matches
Scheduling.c
1#include "main.h"
2#include "Scheduling.h"
3#include "NetSim_Plot.h"
4#pragma comment(lib,"Metrics.lib")
5#include "AdvancedPlots.h"
6#pragma comment(lib,"AdvancedPlots.lib")
7
8enum enum_Buffer_Manipulation_Type
9{
10 ADD = 1,
11 GET,
12};
13#define fnGetList(pstruPacketlist,Priority) (pstruPacketlist+Priority/(Priority_High-Priority_Medium))
14
15//Queuing functions
16enum enum_BUFFER fn_NetSim_DropTail(NetSim_BUFFER*, NetSim_PACKET*);
17enum enum_BUFFER fn_NetSim_RED(NetSim_BUFFER*, NetSim_PACKET*);
18enum enum_BUFFER fn_NetSim_WRED(NetSim_BUFFER*, NetSim_PACKET*);
19
20//Scheduling functions
21NetSim_PACKET* fn_NetSim_Priority(NetSim_BUFFER*, NetSim_PACKET*, int, int);
22NetSim_PACKET* fn_NetSim_FIFO(NetSim_BUFFER*, NetSim_PACKET*, int, int);
23NetSim_PACKET* fn_NetSim_RoundRobin(NetSim_BUFFER*, NetSim_PACKET*, int, int);
24NetSim_PACKET* fn_NetSim_WFQ(NetSim_BUFFER*, NetSim_PACKET*, int, int);
25NetSim_PACKET* fn_NetSim_EDF(NetSim_BUFFER*, NetSim_PACKET*, int, int);
26
27
28UINT64 fn_NetSim_GetPosition_MaximumNumber(UINT64* nCount);
29bool fn_NetSim_GetBufferStatus(NetSim_BUFFER*);
30enum enum_BUFFER fn_NetSim_CheckBuffer(NetSim_BUFFER*, NetSim_PACKET*);
31static void fn_NetSim_DropPackets(NetSim_BUFFER*, NetSim_PACKET*);
32
33/** This function is to check whether buffer list has any packet or not **/
34_declspec(dllexport) bool fn_NetSim_GetBufferStatus(NetSim_BUFFER* pstruBuffer)
35{
36 switch (pstruBuffer->nSchedulingType)
37 {
38 case 0:
39 case SCHEDULING_PRIORITY:
40 case SCHEDULING_EDF:
41 case SCHEDULING_FIFO:
42 return pstruBuffer->pstruPacketlist ? true : false;
43 break;
44 case SCHEDULING_ROUNDROBIN:
45 case SCHEDULING_WFQ:
46 {
47 if (!pstruBuffer->pstruPacketlist) return false;
48
49 PACKET_PRIORITY currPriority = Priority_High;
50
51 do
52 {
53 NetSim_PACKET* pstruTempList = fnGetList(pstruBuffer->pstruPacketlist, currPriority);
54 if (pstruTempList->pstruNextPacket != NULL)
55 return true;
56 currPriority -= Priority_High - Priority_Medium;
57 } while (currPriority > 0);
58 return false;
59 break;
60 }
61 default:
62 return false;
63 break;
64 }
65 return false;
66}
67
68/** This function is to return queuing status based on given algorithm **/
69enum enum_Buffer fn_NetSim_Queuing(NetSim_BUFFER* pstruBuffer, NetSim_PACKET* pstruData)
70{
71 QUEUINGTECHNIQUE Queuing_Technique;
72 int queuing_result;
73 Queuing_Technique = pstruBuffer->queuingTechnique;
74 switch (Queuing_Technique)
75 {
76 case QUEUING_DROPTAIL:
77 queuing_result = fn_NetSim_DropTail(pstruBuffer, pstruData);
78 break;
79 case QUEUING_RED:
80 queuing_result = fn_NetSim_RED(pstruBuffer, pstruData);
81 break;
82 case QUEUING_WRED:
83 queuing_result = fn_NetSim_WRED(pstruBuffer, pstruData);
84 break;
85 default:
86 queuing_result = fn_NetSim_DropTail(pstruBuffer, pstruData);
87 break;
88 }
89
90 if (queuing_result == Buffer_Underflow)
91 return Buffer_Underflow;
92 else
93 return Buffer_Overflow;
94}
95
96/** This function is to add packet to the buffer **/
97_declspec(dllexport)int fn_NetSim_Packet_AddPacketToBuffer(NetSim_BUFFER* pstruBuffer, NetSim_PACKET* pstruData)
98{
99 int nBufferFlag;
100 int nType = 1;
101 SCHEDULING_TYPE Scheduling_Technique;
102
103 nBufferFlag = fn_NetSim_Queuing(pstruBuffer, pstruData);
104
105 if (nBufferFlag == Buffer_Underflow)
106 {
107 NETSIM_ID d = pstruEventDetails->nDeviceId;
108 NETSIM_ID in = pstruEventDetails->nInterfaceId;
109
110 if (pstruBuffer->nSchedulingType != SCHEDULING_NONE)
111 {
112 if (d)
113 {
114 if (pstruBuffer->dMaxBufferSize > pow(10, 6))
115 fnNetSim_buffer_log_write("%lf,%d,%s,%d,Interface_%d (%s),%lf,%s,%s,%s", pstruEventDetails->dEventTime/MILLISECOND, DEVICE_CONFIGID(d), DEVICE_NAME(d),
116 DEVICE_INTERFACE_CONFIGID(d, in), DEVICE_INTERFACE_CONFIGID(d, in), DEVICE_INTERFACE(d, in)->szInterfaceName, pstruBuffer->dCurrentBufferSize, "inf", "N/A", "ENQUEUE");
117 else
118 fnNetSim_buffer_log_write("%lf,%d,%s,%d,Interface_%d (%s),%lf,%lf,%s,%s", pstruEventDetails->dEventTime/MILLISECOND, DEVICE_CONFIGID(d), DEVICE_NAME(d),
119 DEVICE_INTERFACE_CONFIGID(d, in), DEVICE_INTERFACE_CONFIGID(d, in), DEVICE_INTERFACE(d, in)->szInterfaceName, pstruBuffer->dCurrentBufferSize, pstruBuffer->dMaxBufferSize, "N/A", "ENQUEUE");
120 }
121 }
122 pstruBuffer->nQueuedPacket++;
123 Scheduling_Technique = pstruBuffer->nSchedulingType;
124 switch (Scheduling_Technique)
125 {
126 case SCHEDULING_PRIORITY:
127 fn_NetSim_Priority(pstruBuffer, pstruData, nType, 1);
128 break;
129 case SCHEDULING_FIFO:
130 fn_NetSim_FIFO(pstruBuffer, pstruData, nType, 1);
131 break;
132 case SCHEDULING_ROUNDROBIN:
133 fn_NetSim_RoundRobin(pstruBuffer, pstruData, nType, 1);
134 break;
135 case SCHEDULING_WFQ:
136 fn_NetSim_WFQ(pstruBuffer, pstruData, nType, 1);
137 break;
138 case SCHEDULING_EDF:
139 fn_NetSim_EDF(pstruBuffer, pstruData, nType, 1);
140 break;
141 default:
142 fn_NetSim_FIFO(pstruBuffer, pstruData, nType, 1);
143 break;
144 }
145 }
146 else if (nBufferFlag == Buffer_Overflow)
147 {
148
149 NETSIM_ID d = pstruEventDetails->nDeviceId;
150 NETSIM_ID in = pstruEventDetails->nInterfaceId;
151 if (pstruBuffer->nSchedulingType != SCHEDULING_NONE)
152 {
153 if (d)
154 {
155 if (pstruBuffer->dMaxBufferSize > pow(10, 6))
156 fnNetSim_buffer_log_write("%lf,%d,%s,%d,Interface_%d (%s),%lf,%s,%s,%s", pstruEventDetails->dEventTime/MILLISECOND, DEVICE_CONFIGID(d), DEVICE_NAME(d),
157 DEVICE_INTERFACE_CONFIGID(d, in), DEVICE_INTERFACE_CONFIGID(d, in), DEVICE_INTERFACE(d, in)->szInterfaceName, pstruBuffer->dCurrentBufferSize, "inf", "N/A", "DROP");
158 else
159 fnNetSim_buffer_log_write("%lf,%d,%s,%d,Interface_%d (%s),%lf,%lf,%s,%s", pstruEventDetails->dEventTime/MILLISECOND, DEVICE_CONFIGID(d), DEVICE_NAME(d),
160 DEVICE_INTERFACE_CONFIGID(d, in), DEVICE_INTERFACE_CONFIGID(d, in), DEVICE_INTERFACE(d, in)->szInterfaceName, pstruBuffer->dCurrentBufferSize, pstruBuffer->dMaxBufferSize, "N/A", "DROP");
161 }
162 }
163
164 pstruBuffer->nDroppedPacket++;
165 pstruData->nPacketStatus = PacketStatus_Buffer_Dropped;
166 pstruData->nReceiverId = pstruEventDetails->nDeviceId;
167 fn_NetSim_WritePacketTrace(pstruData);
168 fn_NetSim_Packet_FreePacket(pstruData);
169 pstruData = NULL;
170 }
171 else
172 {
173 assert(false);
174 }
175 return 0;
176}
177
178/** This function is to get the packet from the buffer **/
179_declspec(dllexport) NetSim_PACKET* fn_NetSim_GetPacketFromBuffer(NetSim_BUFFER* pstruBuffer, int nFlag)
180{
181
182 int nType = 2;
183 int nScheduling_Technique;
184 NetSim_PACKET* pstruData = NULL;
185 if (fn_NetSim_GetBufferStatus(pstruBuffer))
186 {
187 if (nFlag)
188 pstruBuffer->nDequeuedPacket++;
189 nScheduling_Technique = pstruBuffer->nSchedulingType;
190 switch (nScheduling_Technique)
191 {
192 case SCHEDULING_PRIORITY:
193 pstruData = fn_NetSim_Priority(pstruBuffer, pstruData, nType, nFlag);
194 break;
195 case SCHEDULING_FIFO:
196 pstruData = fn_NetSim_FIFO(pstruBuffer, pstruData, nType, nFlag);
197 break;
198 case SCHEDULING_ROUNDROBIN:
199 pstruData = fn_NetSim_RoundRobin(pstruBuffer, pstruData, nType, nFlag);
200 break;
201 case SCHEDULING_WFQ:
202 pstruData = fn_NetSim_WFQ(pstruBuffer, pstruData, nType, nFlag);
203 break;
204 case SCHEDULING_EDF:
205 pstruData = fn_NetSim_EDF(pstruBuffer, pstruData, nType, nFlag);
206 break;
207 default:
208 pstruData = fn_NetSim_FIFO(pstruBuffer, pstruData, nType, nFlag);
209 break;
210 }
211 }
212
213 if (pstruData == NULL)
214 return NULL;
215
216 if (nFlag &&
217 pstruBuffer->dMaxBufferSize)
218 {
219 double d_NN_DataSize;
220 if (pstruData->pstruNetworkData)
221 d_NN_DataSize = pstruData->pstruNetworkData->dPacketSize;
222 else
223 d_NN_DataSize = pstruData->pstruMacData->dPacketSize;
224 pstruBuffer->dCurrentBufferSize -= (double)((int)d_NN_DataSize);
225 if (pstruBuffer->dCurrentBufferSize < 0)
226 {
227 assert(false);
228 pstruBuffer->dCurrentBufferSize = 0;
229 fnNetSimError("Assert failure in scheduling. Buffer size is negative.\n");
230 }
231 }
232
233 if (pstruBuffer->queuingTechnique == QUEUING_RED && pstruBuffer->dCurrentBufferSize == 0)
234 {
235 ptrQUEUING_RED_VAR queuing_var = pstruBuffer->queuingParam;
236 queuing_var->q_time = pstruEventDetails->dEventTime;
237 }
238
239 if (pstruBuffer->queuingTechnique == QUEUING_WRED && pstruBuffer->dCurrentBufferSize == 0)
240 {
241 ptrQUEUING_WRED_VAR queuing_var = pstruBuffer->queuingParam;
242 queuing_var->q_time = pstruEventDetails->dEventTime;
243 }
244
245 NETSIM_ID d = pstruEventDetails->nDeviceId;
246 NETSIM_ID in = pstruEventDetails->nInterfaceId;
247
248 if (pstruBuffer->nSchedulingType != SCHEDULING_NONE)
249 {
250 if (d && nFlag)
251 {
252 if (pstruBuffer->dMaxBufferSize > pow(10, 6))
253 fnNetSim_buffer_log_write("%lf,%d,%s,%d,Interface_%d (%s),%lf,%s,%s,%s", pstruEventDetails->dEventTime/MILLISECOND, DEVICE_CONFIGID(d), DEVICE_NAME(d),
254 DEVICE_INTERFACE_CONFIGID(d, in), DEVICE_INTERFACE_CONFIGID(d, in), DEVICE_INTERFACE(d, in)->szInterfaceName, pstruBuffer->dCurrentBufferSize, "inf", "N/A", "DEQUEUE");
255 else
256 fnNetSim_buffer_log_write("%lf,%d,%s,%d,Interface_%d (%s),%lf,%lf,%s,%s", pstruEventDetails->dEventTime/MILLISECOND, DEVICE_CONFIGID(d), DEVICE_NAME(d),
257 DEVICE_INTERFACE_CONFIGID(d, in), DEVICE_INTERFACE_CONFIGID(d, in), DEVICE_INTERFACE(d, in)->szInterfaceName, pstruBuffer->dCurrentBufferSize, pstruBuffer->dMaxBufferSize, "N/A", "DEQUEUE");
258 }
259 }
260
261
262 return pstruData;
263}
264
265/** The function will get the array and it will return the Maximum number's position **/
266UINT64 fn_NetSim_GetPosition_MaximumNumber(UINT64* nCount)
267{
268 unsigned long long int nMax;
269 UINT nLoop;
270 UINT64 nFlag = 0;
271 nMax = nCount[0];
272 for (nLoop = 1; nLoop < 4; nLoop++)
273 {
274 if (nCount[nLoop] >= nMax)
275 {
276 nMax = nCount[nLoop];
277 nFlag = nLoop;
278 }
279 }
280
281 return nFlag + 1;
282}
283
284/** Function for dropping packets **/
285static void fn_NetSim_DropPackets(NetSim_BUFFER* pstruBuffer, NetSim_PACKET* pstruData)
286{
287 pstruBuffer->nDroppedPacket++;
288 pstruData->nPacketStatus = PacketStatus_Buffer_Dropped;
289 pstruData->nReceiverId = pstruData->nTransmitterId;
290 fn_NetSim_WritePacketTrace(pstruData);
291 fn_NetSim_Packet_FreePacket(pstruData);
292 pstruData = NULL;
293}
294
295/**
296If the Current buffer size is greater than the Maximum buffer size --> Buffer Overflow
297Otherwise Buffer underflows.
298*/
299enum enum_BUFFER fn_NetSim_CheckBuffer(NetSim_BUFFER* pstruBuffer, NetSim_PACKET* pstruData)
300{
301 double d_NN_DataSize = 0;
302 double ldMaximumBufferSize;
303 double ldCurrentBufferSize;
304 NetSim_PACKET* p = pstruData;
305
306 while (p)
307 {
308 if (pstruData->pstruNetworkData)
309 d_NN_DataSize += pstruData->pstruNetworkData->dPacketSize;
310 else
311 d_NN_DataSize += pstruData->pstruMacData->dPacketSize;
312 p = p->pstruNextPacket;
313 }
314 if (!pstruBuffer->dMaxBufferSize)
315 pstruBuffer->dMaxBufferSize = (double)0xFFFFFFFFFFFFFFFF;
316 ldMaximumBufferSize = pstruBuffer->dMaxBufferSize * 1024 * 1024;
317 ldCurrentBufferSize = pstruBuffer->dCurrentBufferSize + d_NN_DataSize;
318 if (ldCurrentBufferSize <= ldMaximumBufferSize)
319 {
320 //buffer underflow
321 pstruBuffer->dCurrentBufferSize = (double)((int)ldCurrentBufferSize);
322 return Buffer_Underflow;
323 }
324 else
325 //buffer overflow
326 return Buffer_Overflow;
327}
328
329/** Queuing - Packets are dropped only when buffer is full **/
330enum enum_BUFFER fn_NetSim_DropTail(NetSim_BUFFER* pstruBuffer, NetSim_PACKET* pstruData)
331{
332 enum enum_BUFFER checkBuffer = fn_NetSim_CheckBuffer(pstruBuffer, pstruData);
333 if (checkBuffer == Buffer_Underflow)
334 return Buffer_Underflow;
335 else
336 return Buffer_Overflow;
337}
338
339/** Function is used to add packet size to of buffer **/
340static void add_current_size_buffer(NetSim_BUFFER* pstruBuffer, NetSim_PACKET* pstruData)
341{
342 double d_NN_DataSize = 0;
343 double ldCurrentBufferSize;
344 NetSim_PACKET* p = pstruData;
345
346 while (p)
347 {
348 if (pstruData->pstruNetworkData)
349 d_NN_DataSize += pstruData->pstruNetworkData->dPacketSize;
350 else
351 d_NN_DataSize += pstruData->pstruMacData->dPacketSize;
352 p = p->pstruNextPacket;
353 }
354 ldCurrentBufferSize = pstruBuffer->dCurrentBufferSize + d_NN_DataSize;
355 pstruBuffer->dCurrentBufferSize = (double)((int)ldCurrentBufferSize);
356}
357
358/** Function is used to reduce size of buffer(added while checkBuffer) in case of packet drop **/
359static void reduce_current_size_buffer(NetSim_BUFFER* pstruBuffer, NetSim_PACKET* pstruData)
360{
361 double d_NN_DataSize;
362 if (pstruData->pstruNetworkData)
363 d_NN_DataSize = pstruData->pstruNetworkData->dPacketSize;
364 else
365 d_NN_DataSize = pstruData->pstruMacData->dPacketSize;
366 pstruBuffer->dCurrentBufferSize -= (double)((int)d_NN_DataSize);
367 if (pstruBuffer->dCurrentBufferSize < 0)
368 {
369 assert(false);
370 pstruBuffer->dCurrentBufferSize = 0;
371 fnNetSimError("Scheduling--- Buffer size negative. how?????\n");
372 }
373}
374
375/** Helper function for RED Queuing Technique **/
376static enum enum_BUFFER red_algorithm(NetSim_BUFFER* pstruBuffer, NetSim_PACKET* pstruData)
377{
378 ptrQUEUING_RED_VAR queuing_var = pstruBuffer->queuingParam;
379
380 double pb;
381
382 if (queuing_var->min_th <= queuing_var->avg_queue_size &&
383 queuing_var->avg_queue_size < queuing_var->max_th)
384 {
385 queuing_var->count++;
386 pb = queuing_var->max_p * (queuing_var->avg_queue_size - queuing_var->min_th) /
387 (queuing_var->max_th - queuing_var->min_th);
388 if (queuing_var->count > 0 && queuing_var->count > queuing_var->random_value / pb)
389 {
390 queuing_var->count = 0;
391 queuing_var->random_value = NETSIM_RAND_01();
392
393 return Buffer_Overflow;
394 }
395 return Buffer_Underflow;
396 }
397 else if (queuing_var->max_th <= queuing_var->avg_queue_size)
398 {
399 queuing_var->count = -1;
400
401 return Buffer_Overflow;
402 }
403 else
404 {
405 queuing_var->count = -1;
406 return Buffer_Underflow;
407 }
408}
409
410/** Queuing - RED **/
411enum enum_BUFFER fn_NetSim_RED(NetSim_BUFFER* pstruBuffer, NetSim_PACKET* pstruData)
412{
413 enum enum_BUFFER checkBuffer = fn_NetSim_CheckBuffer(pstruBuffer, pstruData);
414 if (checkBuffer == Buffer_Underflow)
415 {
416 reduce_current_size_buffer(pstruBuffer, pstruData);
417 ptrQUEUING_RED_VAR queuing_var = pstruBuffer->queuingParam;
418 double curr_buff_size_in_MB = pstruBuffer->dCurrentBufferSize / 1048576;
419
420 if (curr_buff_size_in_MB == 0)
421 {
422 queuing_var->avg_queue_size = pow((1 - queuing_var->wq), (pstruEventDetails->dEventTime - queuing_var->q_time))
423 * queuing_var->avg_queue_size;
424 }
425 else
426 {
427 queuing_var->avg_queue_size = queuing_var->avg_queue_size +
428 queuing_var->wq * (curr_buff_size_in_MB - queuing_var->avg_queue_size);
429 }
430
431 checkBuffer = red_algorithm(pstruBuffer, pstruData);
432 if (checkBuffer == Buffer_Underflow)
433 add_current_size_buffer(pstruBuffer, pstruData); // Increment current buffer size
434
435 return checkBuffer;
436 }
437 else
438 return Buffer_Overflow;
439}
440
441/** Helper function for WRED Queuing Technique **/
442static enum enum_BUFFER wred_algorithm(NetSim_BUFFER* pstruBuffer, NetSim_PACKET* pstruData,
443 double max_th, double min_th, double max_p, int* count, double* random)
444{
445 ptrQUEUING_WRED_VAR queuing_var = pstruBuffer->queuingParam;
446
447 double pb;
448
449 if (min_th <= queuing_var->avg_queue_size &&
450 queuing_var->avg_queue_size < max_th)
451 {
452 *count = *count + 1;
453 pb = max_p * (queuing_var->avg_queue_size - min_th) /
454 (max_th - min_th);
455 if (*count > 0 && *count > * random / pb)
456 {
457 *count = 0;
458 *random = NETSIM_RAND_01();
459
460 return Buffer_Overflow;
461 }
462 return Buffer_Underflow;
463 }
464 else if (max_th <= queuing_var->avg_queue_size)
465 {
466 *count = -1;
467 return Buffer_Overflow;
468 }
469 else
470 {
471 *count = -1;
472 return Buffer_Underflow;
473 }
474}
475
476/** Queuing - WRED **/
477enum enum_BUFFER fn_NetSim_WRED(NetSim_BUFFER* pstruBuffer, NetSim_PACKET* pstruData)
478{
479 enum enum_BUFFER checkBuffer = fn_NetSim_CheckBuffer(pstruBuffer, pstruData);
480 if (checkBuffer == Buffer_Underflow)
481 {
482 reduce_current_size_buffer(pstruBuffer, pstruData);
483 ptrQUEUING_WRED_VAR queuing_var = pstruBuffer->queuingParam;
484 int index;
485 double curr_max_th;
486 double curr_min_th;
487 double curr_max_p;
488 int* curr_count;
489 double* curr_random;
490 double curr_buff_size_in_MB = pstruBuffer->dCurrentBufferSize / 1048576;
491 int priority = pstruData->nPacketPriority;
492
493 if (curr_buff_size_in_MB == 0)
494 {
495 queuing_var->avg_queue_size = pow((1 - queuing_var->wq), (pstruEventDetails->dEventTime - queuing_var->q_time))
496 * queuing_var->avg_queue_size;
497 }
498 else
499 {
500 queuing_var->avg_queue_size = queuing_var->avg_queue_size +
501 queuing_var->wq * (curr_buff_size_in_MB - queuing_var->avg_queue_size);
502 }
503
504 index = (priority / 2) - 1;
505
506 //adding control packets in queue
507 if (index == -1)
508 {
509 checkBuffer = Buffer_Underflow;
510 }
511 else
512 {
513 curr_max_th = *(queuing_var->max_th + index);
514 curr_min_th = *(queuing_var->min_th + index);
515 curr_max_p = *(queuing_var->max_p + index);
516 curr_count = (queuing_var->count + index);
517 curr_random = (queuing_var->random_value + index);
518
519 checkBuffer = wred_algorithm(pstruBuffer, pstruData, curr_max_th, curr_min_th, curr_max_p, curr_count, curr_random);
520 }
521
522 if (checkBuffer == Buffer_Underflow)
523 add_current_size_buffer(pstruBuffer, pstruData); // Increment current buffer size
524
525 return checkBuffer;
526 }
527 else
528 return Buffer_Overflow;
529}
530
531/**
532If the type is ADD, then all the packets will be added in the buffer based on packet priority
533If the type is GET, then the packets to be retrieved based on the priority
534*/
535NetSim_PACKET* fn_NetSim_Priority(NetSim_BUFFER* pstruBuffer, NetSim_PACKET* pstruData, int nType, int nFlag)
536{
537 switch (nType)
538 {
539 case ADD:
540 if (pstruBuffer->pstruPacketlist)
541 {
542 NetSim_PACKET* pstruTmpBufferPacketList;
543 NetSim_PACKET* pstruPrevPacketList;
544
545 pstruTmpBufferPacketList = pstruBuffer->pstruPacketlist;
546 pstruPrevPacketList = pstruBuffer->pstruPacketlist;
547 if (pstruTmpBufferPacketList->nPacketPriority < pstruData->nPacketPriority)
548 {
549 pstruData->pstruNextPacket = pstruTmpBufferPacketList;
550 pstruBuffer->pstruPacketlist = pstruData;
551 return 0;
552 }
553 while (pstruTmpBufferPacketList)
554 {
555 if (pstruTmpBufferPacketList->nPacketPriority < pstruData->nPacketPriority)
556 {
557 pstruData->pstruNextPacket = pstruTmpBufferPacketList;
558 pstruPrevPacketList->pstruNextPacket = pstruData;
559 break;
560 }
561 else if (!pstruTmpBufferPacketList->pstruNextPacket)
562 {
563 pstruTmpBufferPacketList->pstruNextPacket = pstruData;
564 break;
565 }
566 else
567 {
568 pstruPrevPacketList = pstruTmpBufferPacketList;
569 pstruTmpBufferPacketList = pstruTmpBufferPacketList->pstruNextPacket;
570 }
571 }
572
573 }
574 else
575 pstruBuffer->pstruPacketlist = pstruData;
576 break;
577 case GET:
578 {
579 NetSim_PACKET* pstruPacket;
580 pstruPacket = pstruBuffer->pstruPacketlist;
581 if (nFlag)
582 {
583 pstruBuffer->pstruPacketlist = pstruPacket->pstruNextPacket;
584 pstruPacket->pstruNextPacket = NULL;
585 }
586 return pstruPacket;
587 break;
588 }
589 default:
590 printf("\nInvalid Selection in Buffer\n");
591 break;
592 }
593 return NULL;
594
595}
596/**
597If the type is ADD, then all the packets will be added in the buffer based on the arrival
598If the type is GET, then the packets to be retrieved depends on the arrangement in the queue
599*/
600NetSim_PACKET* fn_NetSim_FIFO(NetSim_BUFFER* pstruBuffer, NetSim_PACKET* pstruData, int nType, int nFlag)
601{
602 NetSim_PACKET* p = pstruData;
603 while (p && p->pstruNextPacket)
604 p = p->pstruNextPacket;
605 switch (nType)
606 {
607 case ADD:
608 if (pstruBuffer->pstruPacketlist)
609 {
610 pstruBuffer->last->pstruNextPacket = pstruData;
611 pstruBuffer->last = p;
612 }
613 else
614 {
615 pstruBuffer->pstruPacketlist = pstruData;
616 pstruBuffer->last = p;
617 }
618 break;
619 case GET:
620 {
621 NetSim_PACKET* pstruPacket;
622 pstruPacket = pstruBuffer->pstruPacketlist;
623 if (nFlag)
624 {
625 pstruBuffer->pstruPacketlist = pstruPacket->pstruNextPacket;
626 if (pstruBuffer->pstruPacketlist == NULL)
627 pstruBuffer->last = NULL;
628 pstruPacket->pstruNextPacket = NULL;
629 }
630 return pstruPacket;
631 break;
632 }
633 default:
634 printf("\nInvalid selection in Buffer\n");
635 break;
636 }
637 return 0;
638}
639/**
640If the type is ADD, then all the packets will be added in the buffer based on packet priority in the corresponding list
641If the type is GET, then the packets to be retrieved in the order of one packet from each list(high priority list,Medium,Normal,Low)
642*/
643NetSim_PACKET* fn_NetSim_RoundRobin(NetSim_BUFFER* pstruBuffer, NetSim_PACKET* pstruData, int nType, int nFlag)
644{
645 switch (nType)
646 {
647 case ADD:
648 {
649 NetSim_PACKET* pstruTmpBufferPacketList;
650 NetSim_PACKET* pstruTempTraversePacketList;
651
652 if (pstruBuffer->pstruPacketlist == NULL)
653 {
654 pstruBuffer->pstruPacketlist = fnpAllocateMemory(5, sizeof * pstruData);
655 }
656 pstruTmpBufferPacketList = pstruBuffer->pstruPacketlist;
657 if (pstruData->nPacketPriority)
658 {
659 pstruTempTraversePacketList = fnGetList(pstruTmpBufferPacketList, pstruData->nPacketPriority);
660
661 while (pstruTempTraversePacketList->pstruNextPacket != NULL)
662 pstruTempTraversePacketList = pstruTempTraversePacketList->pstruNextPacket;
663 pstruTempTraversePacketList->pstruNextPacket = pstruData;
664 }
665 else
666 {
667 pstruTempTraversePacketList = fnGetList(pstruTmpBufferPacketList, Priority_Low);
668 while (pstruTempTraversePacketList->pstruNextPacket != NULL)
669 pstruTempTraversePacketList = pstruTempTraversePacketList->pstruNextPacket;
670 pstruTempTraversePacketList->pstruNextPacket = pstruData;
671 }
672 break;
673 }
674 case GET:
675 {
676 NetSim_PACKET* pstruTemp;
677 NetSim_PACKET* pstruTempList;
678 int nFlag1 = 0;
679 PACKET_PRIORITY nPacketPriority;
680 if (pstruBuffer->pstruPacketlist)
681 {
682 nPacketPriority = pstruBuffer->pstruPacketlist->nPacketPriority;
683 Retry:
684 nFlag1++;
685 if (nFlag1 == 5)
686 return NULL;
687 else
688 {
689 pstruBuffer->pstruPacketlist->nPacketPriority -= Priority_High - Priority_Medium;
690 if (pstruBuffer->pstruPacketlist->nPacketPriority <= 0)
691 pstruBuffer->pstruPacketlist->nPacketPriority = Priority_High;
692
693 pstruTempList = fnGetList(pstruBuffer->pstruPacketlist, pstruBuffer->pstruPacketlist->nPacketPriority);
694 if (pstruTempList->pstruNextPacket != NULL)
695 {
696 pstruTemp = pstruTempList->pstruNextPacket;
697 if (nFlag)
698 {
699 pstruTempList->pstruNextPacket = pstruTemp->pstruNextPacket;
700 pstruTemp->pstruNextPacket = NULL;
701 }
702 else
703 pstruBuffer->pstruPacketlist->nPacketPriority = nPacketPriority;
704 return pstruTemp;
705 }
706 else
707 goto Retry;
708 }
709 }
710 else
711 return NULL;
712 }
713 default:
714 printf("\nInvalid Selection in Buffer\n");
715 break;
716 }
717 return 0;
718}
719
720/**
721If the type is ADD, then all the packets will be added in the buffer based on packet priority in the corresponding list
722If the type is GET, then the packets to be retrieved in the order of maximum weight priority list(High,Medium,Normal,Low)
723*/
724NetSim_PACKET* fn_NetSim_WFQ(NetSim_BUFFER* pstruBuffer, NetSim_PACKET* pstruData, int nType, int nFlag)
725{
726 switch (nType)
727 {
728 case ADD:
729 {
730 NetSim_PACKET* pstruTmpBufferPacketList;
731 NetSim_PACKET* pstruTempTraversePacketList;
732
733 if (pstruBuffer->pstruPacketlist == NULL)
734 {
735 pstruBuffer->pstruPacketlist = fnpAllocateMemory(5, sizeof * pstruData);
736 }
737 pstruTmpBufferPacketList = pstruBuffer->pstruPacketlist;
738 if (pstruData->nPacketPriority)
739 {
740 pstruTempTraversePacketList = fnGetList(pstruTmpBufferPacketList, pstruData->nPacketPriority);
741
742 pstruTempTraversePacketList->nPacketId++;
743
744 while (pstruTempTraversePacketList->pstruNextPacket != NULL)
745 pstruTempTraversePacketList = pstruTempTraversePacketList->pstruNextPacket;
746 pstruTempTraversePacketList->pstruNextPacket = pstruData;
747 }
748 else
749 {
750 pstruTempTraversePacketList = fnGetList(pstruTmpBufferPacketList, Priority_Low);
751
752 pstruTempTraversePacketList->nPacketId++;
753
754 while (pstruTempTraversePacketList->pstruNextPacket != NULL)
755 pstruTempTraversePacketList = pstruTempTraversePacketList->pstruNextPacket;
756 pstruTempTraversePacketList->pstruNextPacket = pstruData;
757 }
758
759 break;
760 }
761 case GET:
762 {
763 UINT64 nCount[4], nPosition;
764 NetSim_PACKET* pstruTempList;
765 NetSim_PACKET* pstruTemp;
766 NetSim_PACKET* pstruHighPriorityList;
767 NetSim_PACKET* pstruMediumPriorityList;
768 NetSim_PACKET* pstruNormalPriorityList;
769 NetSim_PACKET* pstruLowPriorityList;
770
771 pstruLowPriorityList = fnGetList(pstruBuffer->pstruPacketlist, Priority_Low);
772 nCount[0] = pstruLowPriorityList->nPacketId * 1;
773
774 pstruNormalPriorityList = fnGetList(pstruBuffer->pstruPacketlist, Priority_Normal);
775 nCount[1] = pstruNormalPriorityList->nPacketId * 2;
776
777 pstruMediumPriorityList = fnGetList(pstruBuffer->pstruPacketlist, Priority_Medium);
778 nCount[2] = pstruMediumPriorityList->nPacketId * 3;
779
780 pstruHighPriorityList = fnGetList(pstruBuffer->pstruPacketlist, Priority_High);
781 nCount[3] = pstruHighPriorityList->nPacketId * 4;
782
783 nPosition = fn_NetSim_GetPosition_MaximumNumber(nCount);
784
785 pstruTempList = pstruBuffer->pstruPacketlist + nPosition;
786
787 if (pstruTempList && pstruTempList->pstruNextPacket)
788 {
789 pstruTempList->nPacketId--;
790 pstruTemp = pstruTempList->pstruNextPacket;
791 if (nFlag)
792 {
793 pstruTempList->pstruNextPacket = pstruTemp->pstruNextPacket;
794 pstruTemp->pstruNextPacket = NULL;
795 }
796 else
797 pstruTempList->nPacketId++;
798 return pstruTemp;
799 }
800 else
801 return NULL;
802 }
803 default:
804 printf("\nInvalid Selection in Buffer\n");
805 break;
806 }
807 return 0;
808}
809
810/** Helper function for EDF Scheduling Technique **/
811static void edf_algorithm_drop_expired_packets(NetSim_BUFFER* pstruBuffer)
812{
813 ptrSCHEDULING_EDF_VAR scheduling_var = pstruBuffer->schedulingParam;
814
815 NetSim_PACKET* pstruPacket_prev;
816 NetSim_PACKET* pstruPacket_itr;
817 NetSim_PACKET* pstruPacket_drop;
818 int index;
819 double curr_max_latency;
820 double curr_deadline;
821
822 pstruPacket_itr = pstruBuffer->pstruPacketlist;
823 pstruPacket_prev = pstruBuffer->pstruPacketlist;
824
825 while (pstruPacket_itr)
826 {
827 index = pstruPacket_itr->nQOS - 1;
828 if (index != -1)
829 {
830 curr_max_latency = *(scheduling_var->max_latency + index) * 1000;
831 curr_deadline = curr_max_latency - (pstruEventDetails->dEventTime -
832 pstruPacket_itr->dEventTime);
833 if (curr_deadline < 0)
834 {
835 //drop packet from buffer
836 pstruPacket_drop = pstruPacket_itr;
837 if (pstruBuffer->pstruPacketlist == pstruPacket_itr)
838 {
839 pstruPacket_itr = pstruPacket_itr->pstruNextPacket;
840 pstruPacket_prev = pstruPacket_itr;
841 pstruBuffer->pstruPacketlist = pstruPacket_itr;
842 if (pstruPacket_itr == NULL)
843 pstruBuffer->last = NULL;
844 }
845 else
846 {
847 pstruPacket_itr = pstruPacket_itr->pstruNextPacket;
848 pstruPacket_prev->pstruNextPacket = pstruPacket_itr;
849 if (pstruPacket_itr == NULL)
850 pstruBuffer->last = pstruPacket_prev;
851 }
852 fn_NetSim_DropPackets(pstruBuffer, pstruPacket_drop);
853 continue;
854 }
855 }
856 pstruPacket_prev = pstruPacket_itr;
857 pstruPacket_itr = pstruPacket_itr->pstruNextPacket;
858 }
859}
860
861/** Helper function for EDF Scheduling Technique **/
862static NetSim_PACKET* edf_algorithm_get_earliest_deadline_packet(NetSim_BUFFER* pstruBuffer)
863{
864 ptrSCHEDULING_EDF_VAR scheduling_var = pstruBuffer->schedulingParam;
865
866 NetSim_PACKET* pstruPacket_itr;
867 NetSim_PACKET* pstruPacket = NULL;
868 int index;
869 double curr_max_latency;
870 double curr_deadline;
871 double earliest_deadline = (double)0xFFFFFFFFFFFFFFFF;
872
873 pstruPacket_itr = pstruBuffer->pstruPacketlist;
874 while (pstruPacket_itr)
875 {
876 index = pstruPacket_itr->nQOS - 1;
877 if (index == -1)
878 return pstruPacket_itr;
879
880 curr_max_latency = *(scheduling_var->max_latency + index) * 1000;
881 curr_deadline = curr_max_latency - (pstruEventDetails->dEventTime -
882 pstruPacket_itr->dEventTime);
883 if (curr_deadline < earliest_deadline)
884 {
885 pstruPacket = pstruPacket_itr;
886 earliest_deadline = curr_deadline;
887 }
888 pstruPacket_itr = pstruPacket_itr->pstruNextPacket;
889 }
890 return pstruPacket;
891}
892
893/**
894If the type is ADD, then all the packets will be added in the buffer based on arrival
895If the type is GET, then the expired packets are dropped from buffer and earliest deadline packet is served from the buffer
896*/
897NetSim_PACKET* fn_NetSim_EDF(NetSim_BUFFER* pstruBuffer, NetSim_PACKET* pstruData,
898 int nType, int nFlag)
899{
900 ptrSCHEDULING_EDF_VAR scheduling_var = pstruBuffer->schedulingParam;
901 NetSim_PACKET* p = pstruData;
902 while (p && p->pstruNextPacket)
903 p = p->pstruNextPacket;
904
905 switch (nType)
906 {
907 case ADD:
908 if (pstruBuffer->pstruPacketlist)
909 {
910 pstruBuffer->last->pstruNextPacket = pstruData;
911 pstruBuffer->last = p;
912 }
913 else
914 {
915 pstruBuffer->pstruPacketlist = pstruData;
916 pstruBuffer->last = p;
917 }
918 break;
919 case GET:
920 {
921 NetSim_PACKET* pstruPacket;
922 edf_algorithm_drop_expired_packets(pstruBuffer);
923 pstruPacket = edf_algorithm_get_earliest_deadline_packet(pstruBuffer);
924
925 if (nFlag && pstruPacket != NULL)
926 {
927 NetSim_PACKET* pstruPacket_itr = pstruBuffer->pstruPacketlist;
928
929 if (pstruPacket_itr == pstruPacket)
930 {
931 pstruBuffer->pstruPacketlist = pstruPacket->pstruNextPacket;
932 if (pstruBuffer->pstruPacketlist == NULL)
933 pstruBuffer->last = NULL;
934 }
935 else
936 {
937 while (pstruPacket_itr->pstruNextPacket != pstruPacket)
938 pstruPacket_itr = pstruPacket_itr->pstruNextPacket;
939 pstruPacket_itr->pstruNextPacket = pstruPacket->pstruNextPacket;
940 if (pstruPacket_itr->pstruNextPacket == NULL)
941 pstruBuffer->last = pstruPacket_itr;
942 }
943 pstruPacket->pstruNextPacket = NULL;
944 }
945 return pstruPacket;
946 break;
947 }
948 default:
949 printf("\nInvalid selection in Buffer\n");
950 break;
951 }
952 return 0;
953}