NetSim Source Code Help
Loading...
Searching...
No Matches
Medium.c
Go to the documentation of this file.
1/************************************************************************************
2* Copyright (C) 2021 *
3* TETCOS, Bangalore. India *
4* *
5* Tetcos owns the intellectual property rights in the Product and its content. *
6* The copying, redistribution, reselling or publication of any or all of the *
7* Product or its content without express prior written consent of Tetcos is *
8* prohibited. Ownership and / or any other right relating to the software and all *
9* intellectual property rights therein shall remain at all times with Tetcos. *
10* *
11* This source code is licensed per the NetSim license agreement. *
12* *
13* No portion of this source code may be used as the basis for a derivative work, *
14* or used, for any purpose other than its intended use per the NetSim license *
15* agreement. *
16* *
17* This source code and the algorithms contained within it are confidential trade *
18* secrets of TETCOS and may not be used as the basis for any other software, *
19* hardware, product or service. *
20* *
21* Author: Shashi Kant Suman *
22* *
23* ----------------------------------------------------------------------------------*/
24#define _NETSIM_MDEIUM_CODE_
25#include "main.h"
26#include "Medium.h"
27#include "ErrorModel.h"
28#include "PropagationModel.h"
29#pragma comment(lib,"NetworkStack.lib")
30#pragma comment(lib,"Metrics.lib")
31#pragma comment(lib,"PropagationModel.lib")
32//#define _MEDIUM_LOG_
33
34typedef struct stru_Packet_info
35{
42 double endTime_us;
44 double codeRate;
48
53
54typedef struct stru_Device
55{
63 double dCodeRate;
65
68
71 void* (*propagationinfo_find)(NETSIM_ID, NETSIM_ID, NETSIM_ID, NETSIM_ID);
75
76typedef struct stru_medium
77{
83 NETSIM_ID devIf)
84{
85 if (!devId || !devIf)
86 fnNetSimError("Device id = %d, device interface = %d is not a valid input for %s,",
87 devId,
88 devIf,
89 __FUNCTION__);
90 if (medium.devices &&
91 medium.devices[devId - 1])
92 return medium.devices[devId - 1][devIf - 1];
93 return NULL;
94}
95
96
97static FILE* fplog = NULL;
98static void write_log(char* format,...)
99{
100#ifdef _MEDIUM_LOG_
101 if (fplog == NULL)
102 {
103 char str[BUFSIZ];
104 sprintf(str, "%s\\%s", pszIOLogPath, "medium.log");
105 fplog = fopen(str, "w");
106 }
107 va_list ls;
108 va_start(ls, format);
109 vfprintf(fplog, format, ls);
110 fflush(fplog);
111#else
112 format;
113#endif
114}
115
116static double GetRXPowerdBm(NETSIM_ID t, NETSIM_ID ti, NETSIM_ID r, NETSIM_ID ri, double time)
117{
119 if (!dm)
120 {
121 fnNetSimError("Device %d, interface %d is not added to medium before transmission.",
122 t, ti);
123 return NEGATIVE_DBM;
124 }
125
126 PPROPAGATION_INFO info = dm->propagationinfo_find(t, ti, r, ri);
127 if (info == NULL)
128 {
129 fnNetSimErrorandStop("Propagation info is NULL between %d:%d-%d:%d\n", t, ti, r, ri);
130 return NEGATIVE_DBM;
131 }
132 return _propagation_get_received_power_dbm(info, time);
133}
134
136 NETSIM_ID ifid,
137 double dFrequency_MHz,
138 double dBandwidth_MHz,
139 double dRxSensitivity_dBm,
140 double dEdThreshold_dBm,
141 void(*medium_change_callback)(NETSIM_ID, NETSIM_ID, bool,NetSim_PACKET*),
142 bool(*isRadioIdle)(NETSIM_ID, NETSIM_ID),
143 bool(*isTransmitterBusy)(NETSIM_ID, NETSIM_ID),
144 void*(*propagationinfo_find)(NETSIM_ID, NETSIM_ID, NETSIM_ID, NETSIM_ID),
145 void(*packetsentnotify)(NETSIM_ID,NETSIM_ID,NetSim_PACKET*))
146{
147 ptrDEVICE_IN_MEDIUM dm = calloc(1, sizeof * dm);
148 dm->deviceId = d;
149 dm->interfaceId = ifid;
150 dm->dEDThreshold_dBm = dEdThreshold_dBm;
151 dm->dRxSensitivity_dBm = dRxSensitivity_dBm;
152 dm->frequency_MHz = dFrequency_MHz;
153 dm->bandwidth_MHz = dBandwidth_MHz;
155 dm->medium_change_callback = medium_change_callback;
156 dm->isRadioIdle = isRadioIdle;
157 dm->isTranmitterBusy = isTransmitterBusy;
158 dm->propagationinfo_find = propagationinfo_find;
159 dm->packetSentNotify = packetsentnotify;
160
161 if (!medium.devices)
163 if (!medium.devices[d - 1])
164 medium.devices[d - 1] = calloc(DEVICE(d)->nNumOfInterface, sizeof * medium.devices[d - 1]);
165 medium.devices[d - 1][ifid - 1] = dm;
166}
167
168_declspec(dllexport) void medium_update_frequency(NETSIM_ID d, NETSIM_ID in, double f_MHz)
169{
171 if (!dm)
172 {
173 fnNetSimError("%s is called without adding device %d:%d to medium. use medium_add_device to add the device.\n",
174 __FUNCTION__, d, in);
175 return;
176 }
177 dm->frequency_MHz = f_MHz;
178}
179
180_declspec(dllexport) void medium_update_bandwidth(NETSIM_ID d, NETSIM_ID in, double bw_MHz)
181{
183 if (!dm)
184 {
185 fnNetSimError("%s is called without adding device %d:%d to medium. use medium_add_device to add the device.\n",
186 __FUNCTION__, d, in);
187 return;
188 }
189 dm->bandwidth_MHz = bw_MHz;
190}
191
192_declspec(dllexport) void medium_update_rxsensitivity(NETSIM_ID d, NETSIM_ID in, double p_dbm)
193{
195 if (!dm)
196 {
197 fnNetSimError("%s is called without adding device %d:%d to medium. use medium_add_device to add the device.\n",
198 __FUNCTION__, d, in);
199 return;
200 }
201 dm->dRxSensitivity_dBm = p_dbm;
202}
203
204_declspec(dllexport) void medium_update_edthershold(NETSIM_ID d, NETSIM_ID in, double p_dbm)
205{
207 if (!dm)
208 {
209 fnNetSimError("%s is called without adding device %d:%d to medium. use medium_add_device to add the device.\n",
210 __FUNCTION__, d, in);
211 return;
212 }
213 dm->dEDThreshold_dBm = p_dbm;
214}
215
216_declspec(dllexport) void medium_update_modulation(NETSIM_ID d, NETSIM_ID in, PHY_MODULATION m, double coderate)
217{
219 if (!dm)
220 {
221 fnNetSimError("%s is called without adding device %d:%d to medium. use medium_add_device to add the device.\n",
222 __FUNCTION__, d, in);
223 return;
224 }
225 dm->modulation = m;
226 dm->dCodeRate = coderate;
227}
228
229_declspec(dllexport) void medium_update_datarate(NETSIM_ID d, NETSIM_ID in, double r_mbps)
230{
232 if (!dm)
233 {
234 fnNetSimError("%s is called without adding device %d:%d to medium. use medium_add_device to add the device.\n",
235 __FUNCTION__, d, in);
236 return;
237 }
238 dm->dDataRate_mbps = r_mbps;
239}
240
242 NETSIM_ID ifId)
243{
245 if (dm)
246 {
247 free(dm);
248 medium.devices[d - 1][ifId - 1] = NULL;
249 }
250}
251
253 NETSIM_ID txId,
254 NETSIM_ID txIf,
255 NETSIM_ID rxId,
256 NETSIM_ID rxIf)
257{
259
260 ptrPACKETINFO p = calloc(1, sizeof* p);
261 p->packet = packet;
262 p->rxId = rxId;
263 p->rxIf = rxIf;
265 p->endTime_us = packet->pstruPhyData->dEndTime;
266 p->txId = txId;
267 p->txIf = txIf;
268
269 p->codeRate = dm->dCodeRate;
273 p->modulation = dm->modulation;
274 p->dRXPower_dbm = GetRXPowerdBm(txId, txIf, rxId, rxIf, p->startTime_us);
276
278 {
280 while (t->next)
281 t = t->next;
282 t->next = p;
283 }
284 else
285 {
287 }
288 write_log("New Packet %d,TX=%d-%d,RX=%d-%d,RxPower=%lf,\n",
289 p->packet->nPacketId == 0 ? p->packet->nControlDataType * -1 : p->packet->nPacketId,
290 txId, txIf, rxId, rxIf,
291 p->dRXPower_dbm);
292 return p;
293}
294
296{
298 ptrPACKETINFO pr = NULL;
299 while (p)
300 {
301 if (p->packet == packet)
302 {
303 if (pr)
304 {
305 pr->next = p->next;
306 break;
307 }
308 else
309 {
311 break;
312 }
313 }
314 pr = p;
315 p = p->next;
316 }
317 p->next = NULL;
318 write_log("remove Packet %d,TX=%d-%d,RX=%d-%d,RxPower=%lf,\n",
319 p->packet->nPacketId == 0 ? p->packet->nControlDataType * -1 : p->packet->nPacketId,
320 p->txId, p->txIf, p->rxId, p->rxIf,
321 p->dRXPower_dbm);
322 return p;
323}
324
326{
327 free(info);
328}
329
330#define BOLTZMANN 1.38064852e-23 //m2kgs-2K-1
331#define TEMPERATURE 300 //kelvin
332static double compute_sinr(double p, double i, double bw)
333{
334 double noise = BOLTZMANN * TEMPERATURE * bw * 1000000; //in W
335 double Pmw = DBM_TO_MW(p);
336 double imw = DBM_TO_MW(i);
337 noise *= 1000; // in mW
338 return MW_TO_DBM(Pmw / (noise + imw));
339}
340
341static double GetRXPowerMW(NETSIM_ID t, NETSIM_ID ti, NETSIM_ID r, NETSIM_ID ri, double time)
342{
343 return DBM_TO_MW(GetRXPowerdBm(t, ti, r, ri, time));
344}
345
347{
348 info;
350 while (i)
351 {
352 /*if (i->txId == info->txId &&
353 i->txIf == info->txIf &&
354 i != info)
355 {
356 i = i->next;
357 continue;
358 }*/
360
361 double pdbm = GetRXPowerdBm(i->txId, i->txIf,
362 i->rxId, i->rxIf,
363 i->startTime_us);
364 double p = DBM_TO_MW(pdbm);
365
366 double interference = dm->dCummulativeReceivedPower_mw - p;
367 double interferencedbm = MW_TO_DBM(interference);
368
369 i->dMaxInterference_dbm = max(i->dMaxInterference_dbm, interferencedbm);
370
371 //if (dm->isTranmitterBusy(dm->deviceId, dm->interfaceId)) // Transmitter refers to transceiver.
372 //{
373 // i->packet->nPacketStatus = PacketStatus_Collided; // Also receiving when transmitting
374 // write_log("Packet %d collided due to %d-%d busy,\n",
375 // i->packet->nPacketId == 0 ? i->packet->nControlDataType * -1 : i->packet->nPacketId,
376 // dm->deviceId, dm->interfaceId);
377 //}
378
379 i = i->next;
380 }
381}
382
384{
386 while (i)
387 {
388 if (i != info)
389 {
390 if (i->txId == info->txId &&
391 i->txIf == info->txIf)
392 return true;
393 }
394 i = i->next;
395 }
396 return false;
397}
398
399static bool CheckFrequencyInterfrence(double dFrequency1, double dFrequency2, double bandwidth)
400{
401 if (dFrequency1 > dFrequency2)
402 {
403 if ((dFrequency1 - dFrequency2) >= bandwidth)
404 return false; // no interference
405 else
406 return true; // interference
407 }
408 else
409 {
410 if ((dFrequency2 - dFrequency1) >= bandwidth)
411 return false; // no interference
412 else
413 return true; // interference
414 }
415}
416
418{
419 ptrDEVICE_IN_MEDIUM txdm = medium_find_device(info->txId, info->txIf);
420 if (!txdm)
421 {
422 fnNetSimError("Device %d, interface %d is not added to medium before transmission.",
423 info->txId, info->txIf);
424 return;
425 }
426
427 NETSIM_ID nLoop, nLoopInterface;
428 for (nLoop = 1; nLoop <= NETWORK->nDeviceCount; nLoop++)
429 {
430 for (nLoopInterface = 1; nLoopInterface <= DEVICE(nLoop)->nNumOfInterface; nLoopInterface++)
431 {
432 ptrDEVICE_IN_MEDIUM dm = medium_find_device(nLoop, nLoopInterface);
433 if (!dm)
434 continue;
435
437 continue; //Different band
438
439
440 double p = GetRXPowerMW(txdm->deviceId, txdm->interfaceId,
441 dm->deviceId, dm->interfaceId,
442 info->startTime_us);
443
445
447
448 write_log("\tTotal recv power of %d-%d = %lf\n", dm->deviceId, dm->interfaceId,
450
451 if (nLoop == info->rxId &&
452 nLoopInterface == info->rxIf) continue; // Ignore receiver
453 if (nLoop == info->txId &&
454 nLoopInterface == info->txIf) continue; // Ignore transmitter
455
458 dm->medium_change_callback(dm->deviceId, dm->interfaceId, true, info->packet);
459 double pdbm = GetRXPowerdBm(info->txId, info->txIf, dm->deviceId, dm->interfaceId, info->startTime_us);
460 if (pdbm > dm->dEDThreshold_dBm && dm->packetSentNotify)
461 dm->packetSentNotify(dm->deviceId, dm->interfaceId, info->packet);
462 }
463 }
464}
465
467{
468 ptrDEVICE_IN_MEDIUM txdm = medium_find_device(info->txId, info->txIf);
469 if (!txdm)
470 {
471 fnNetSimError("Device %d, interface %d is not added to medium before transmission.",
472 info->txId, info->txIf);
473 return;
474 }
475
476 NETSIM_ID nLoop, nLoopInterface;
477 for (nLoop = 1; nLoop <= NETWORK->nDeviceCount; nLoop++)
478 {
479 for (nLoopInterface = 1; nLoopInterface <= DEVICE(nLoop)->nNumOfInterface; nLoopInterface++)
480 {
481 if (nLoop == info->txId &&
482 nLoopInterface == info->txIf)
483 {
484 if(txdm->isRadioIdle(txdm->deviceId, txdm->interfaceId) &&
486 txdm->medium_change_callback(txdm->deviceId, txdm->interfaceId, false, NULL);
487 //continue;
488 }
489
490 ptrDEVICE_IN_MEDIUM dm = medium_find_device(nLoop, nLoopInterface);
491 if (!dm)
492 continue;
493
495 continue; //Different band
496
497
499 dm->deviceId, dm->interfaceId,
500 info->startTime_us);
501
503
504 if (nLoop == info->rxId &&
505 nLoopInterface == info->rxIf) continue; // Ignore receiver
506 if (nLoop == info->txId &&
507 nLoopInterface == info->txIf) continue; // Ignore transmitter
508
511 dm->medium_change_callback(dm->deviceId, dm->interfaceId, false, NULL);
512 }
513 }
514}
515
517{
519 double i = info->dMaxInterference_dbm;
520 double p = info->dRXPower_dbm;
521 double w = info->dBandwidth_MHz;
523 info->txId, info->txIf,
524 info->rxId, info->rxIf));
525 p -= f;
526 double ber = calculate_FEC_BER(info->modulation, info->codeRate, p, i, w, info->dDataRate_mbps);
529 {
532 write_log("Packet %d errored, BER=%lf, Interference=%lf, RXPower=%lf,\n",
533 info->packet->nPacketId == 0 ? info->packet->nControlDataType * -1 : info->packet->nPacketId,
534 ber, i, p);
535 }
536}
537
539 NETSIM_ID txId,
540 NETSIM_ID txIf,
541 NETSIM_ID rxId,
542 NETSIM_ID rxIf)
543{
544 ptrPACKETINFO info = packetInfo_add(packet, txId, txIf, rxId, rxIf);
546 return;
549}
550
552{
553 ptrPACKETINFO info = packetInfo_remove(packet);
557 packetInfo_free(info);
558}
559
561 NETSIM_ID in)
562{
565}
unsigned int NETSIM_ID
Definition: Animation.h:45
#define NETSIM_ID
Definition: CLIInterface.h:46
double calculate_FEC_BER(PHY_MODULATION modulation, double codingRate, double dReceivedPower_dBm, double interferencePower_dBm, double dBandwidth_MHz, double dataRate_mbps)
#define _declspec(dllexport)
This function is used to trigger the update.
Definition: Linux.h:41
#define fnNetSimError(x,...)
Definition: Linux.h:56
#define max(a, b)
Definition: Linux.h:107
struct stru_medium * ptrMEDIUM
static MEDIUM medium
Definition: Medium.c:81
static void medium_remove_device(NETSIM_ID d, NETSIM_ID ifId)
Definition: Medium.c:241
struct stru_Packet_info PACKETINFO
static ptrDEVICE_IN_MEDIUM medium_find_device(NETSIM_ID devId, NETSIM_ID devIf)
Definition: Medium.c:82
struct stru_medium MEDIUM
static void update_power_due_to_transmission(ptrPACKETINFO info)
Definition: Medium.c:417
static void medium_update_interference(ptrPACKETINFO info)
Definition: Medium.c:346
static void update_power_due_to_transmission_stop(ptrPACKETINFO info)
Definition: Medium.c:466
struct stru_Packet_info * ptrPACKETINFO
static void write_log(char *format,...)
Definition: Medium.c:98
static double GetRXPowerdBm(NETSIM_ID t, NETSIM_ID ti, NETSIM_ID r, NETSIM_ID ri, double time)
Definition: Medium.c:116
static bool isAnypacketIsThereForThisTransmitter(ptrPACKETINFO info)
Definition: Medium.c:383
void medium_update_edthershold(NETSIM_ID d, NETSIM_ID in, double p_dbm)
Definition: Medium.c:204
static double GetRXPowerMW(NETSIM_ID t, NETSIM_ID ti, NETSIM_ID r, NETSIM_ID ri, double time)
Definition: Medium.c:341
static ptrPACKETINFO packetInfo_add(NetSim_PACKET *packet, NETSIM_ID txId, NETSIM_ID txIf, NETSIM_ID rxId, NETSIM_ID rxIf)
Definition: Medium.c:252
static void medium_mark_packet_error(ptrPACKETINFO info)
Definition: Medium.c:516
void medium_update_rxsensitivity(NETSIM_ID d, NETSIM_ID in, double p_dbm)
Definition: Medium.c:192
bool medium_isIdle(NETSIM_ID d, NETSIM_ID in)
Definition: Medium.c:560
static FILE * fplog
Definition: Medium.c:97
struct stru_Device * ptrDEVICE_IN_MEDIUM
#define BOLTZMANN
Definition: Medium.c:330
static ptrPACKETINFO packetInfo_remove(NetSim_PACKET *packet)
Definition: Medium.c:295
static bool CheckFrequencyInterfrence(double dFrequency1, double dFrequency2, double bandwidth)
Definition: Medium.c:399
void medium_notify_packet_received(NetSim_PACKET *packet)
Definition: Medium.c:551
static double compute_sinr(double p, double i, double bw)
Definition: Medium.c:332
void medium_update_bandwidth(NETSIM_ID d, NETSIM_ID in, double bw_MHz)
Definition: Medium.c:180
void medium_update_datarate(NETSIM_ID d, NETSIM_ID in, double r_mbps)
Definition: Medium.c:229
static void packetInfo_free(ptrPACKETINFO info)
Definition: Medium.c:325
void medium_update_frequency(NETSIM_ID d, NETSIM_ID in, double f_MHz)
Definition: Medium.c:168
struct stru_Device DEVICE_IN_MEDIUM
void medium_update_modulation(NETSIM_ID d, NETSIM_ID in, PHY_MODULATION m, double coderate)
Definition: Medium.c:216
void medium_add_device(NETSIM_ID d, NETSIM_ID ifid, double dFrequency_MHz, double dBandwidth_MHz, double dRxSensitivity_dBm, double dEdThreshold_dBm, void(*medium_change_callback)(NETSIM_ID, NETSIM_ID, bool, NetSim_PACKET *), bool(*isRadioIdle)(NETSIM_ID, NETSIM_ID), bool(*isTransmitterBusy)(NETSIM_ID, NETSIM_ID), void *(*propagationinfo_find)(NETSIM_ID, NETSIM_ID, NETSIM_ID, NETSIM_ID), void(*packetsentnotify)(NETSIM_ID, NETSIM_ID, NetSim_PACKET *))
Definition: Medium.c:135
#define TEMPERATURE
Definition: Medium.c:331
void medium_notify_packet_send(NetSim_PACKET *packet, NETSIM_ID txId, NETSIM_ID txIf, NETSIM_ID rxId, NETSIM_ID rxIf)
Definition: Medium.c:538
#define free(p)
Definition: Memory.h:31
#define calloc(c, s)
Definition: Memory.h:29
PACKET_STATUS fn_NetSim_Packet_DecideError(double dBER, long double dPacketSize)
@ PacketStatus_Error
Definition: Packet.h:102
@ PacketStatus_NoError
Definition: Packet.h:101
@ PacketStatus_Collided
Definition: Packet.h:103
#define MW_TO_DBM(mw)
#define DBM_TO_MW(dbm)
double _propagation_get_received_power_dbm(PPROPAGATION_INFO info, double time)
Used to the received power in dBm over time.
#define NEGATIVE_DBM
double _propagation_calculate_fadingloss(PPROPAGATION_INFO info)
Used to calculate the fading loss. Fading model and parameter must be set in PROPAGATION structure wi...
#define DEVICE(DeviceId)
Definition: Stack.h:769
#define NEGATIVE_INFINITY
Definition: Stack.h:69
EXPORTED char * pszIOLogPath
Definition: Stack.h:843
EXPORTED struct stru_NetSim_Network * NETWORK
Definition: Stack.h:742
enum enum_Modulation PHY_MODULATION
uint f(uint state, uchar key[])
Definition: des.c:172
enum enum_PacketStatus PACKET_STATUS
Definition: main.h:128
void(* medium_change_callback)(NETSIM_ID, NETSIM_ID, bool, NetSim_PACKET *)
Definition: Medium.c:69
double bandwidth_MHz
Definition: Medium.c:59
double frequency_MHz
Definition: Medium.c:58
bool(* isTranmitterBusy)(NETSIM_ID, NETSIM_ID)
Definition: Medium.c:72
double dCodeRate
Definition: Medium.c:63
double dEDThreshold_dBm
Definition: Medium.c:61
NETSIM_ID deviceId
Definition: Medium.c:56
NETSIM_ID interfaceId
Definition: Medium.c:57
double dCummulativeReceivedPower_mw
Definition: Medium.c:66
void *(* propagationinfo_find)(NETSIM_ID, NETSIM_ID, NETSIM_ID, NETSIM_ID)
Definition: Medium.c:71
double dCummulativeReceivedPower_dbm
Definition: Medium.c:67
bool(* isRadioIdle)(NETSIM_ID, NETSIM_ID)
Definition: Medium.c:70
double dDataRate_mbps
Definition: Medium.c:64
double dRxSensitivity_dBm
Definition: Medium.c:60
void(* packetSentNotify)(NETSIM_ID, NETSIM_ID, NetSim_PACKET *)
Definition: Medium.c:73
PHY_MODULATION modulation
Definition: Medium.c:62
long long int nPacketId
Definition: Packet.h:256
PACKET_STATUS nPacketStatus
Definition: Packet.h:272
struct stru_NetSim_Packet_PhyLayer * pstruPhyData
Definition: Packet.h:277
unsigned int nControlDataType
Definition: Packet.h:258
double dDataRate_mbps
Definition: Medium.c:45
struct stru_Packet_info * next
Definition: Medium.c:51
NetSim_PACKET * packet
Definition: Medium.c:36
NETSIM_ID rxId
Definition: Medium.c:39
double dRXPower_dbm
Definition: Medium.c:50
double startTime_us
Definition: Medium.c:41
NETSIM_ID txId
Definition: Medium.c:37
double dMaxInterference_dbm
Definition: Medium.c:49
NETSIM_ID txIf
Definition: Medium.c:38
double codeRate
Definition: Medium.c:44
PHY_MODULATION modulation
Definition: Medium.c:43
double dBandwidth_MHz
Definition: Medium.c:47
NETSIM_ID rxIf
Definition: Medium.c:40
double endTime_us
Definition: Medium.c:42
double dFrequency_MHz
Definition: Medium.c:46
ptrDEVICE_IN_MEDIUM ** devices
Definition: Medium.c:78
ptrPACKETINFO transmissionPacket
Definition: Medium.c:79