% Version 1.0
% CSMA/CA SIMULATOR based on the simplified model for 802.15.4 with
% acknowledgements and retransmissions, presented in the following paper:
%
% A. Faridi, M.R. Palattella, A. Lozano, Mischa Dohler, G. Boggia,
% A. Grieco and P. Camarda, "Comprehensive Evaluation of the IEEE
% 802.15.4 MAC Layer Performance with Retransmissions," IEEE Transactions
% on Vehicular Technology, Vol. 59, No. 8, pp 3917-3932, Oct. 2010.
%
% Which is available at:
% http://ieeexplore.ieee.org/xpls/abs_all.jsp?arnumber=5540318
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% This file is licensed under the Creative Commons Attribution 3.0 %
% Unported license (http://creativecommons.org/licenses/by/3.0/). %
% %
% You are free: %
% * to share : to copy, distribute and transmit the work %
% * to remix : to adapt the work %
% %
% Under the following condition: %
% * attribution : You must attribute the work in the manner %
% specified by the author or licensor (but not in any way %
% that suggests that they endorse you or your use of the %
% work). %
% %
% To attribute, please cite the following article in your work: %
% A. Faridi, M.R. Palattella, A. Lozano, Mischa Dohler, G. Boggia, %
% A. Grieco and P. Camarda, "Comprehensive Evaluation of the IEEE %
% 802.15.4 MAC Layer Performance with Retransmissions," IEEE Trans. on %
% Vehicular Technology, Vol. 59, No. 8, pp 3917-3932, Oct. 2010. %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clear
close all
t_start = clock
tt = 6 % the simulation will run for 10^tt (recommended value: tt = 8)
% L is the packet length. Always set minL = maxL. See explanation for LL.
minL = 7;
maxL = 7;
stepL = 1;
% N is the number of nodes in the network
minN = 2;
maxN = 30;
stepN = 1;
aMinBE = 3;
aMaxBE = 5;
M = 4; % max(NB)
R = 3; % max # retransmission
W0 = 2^aMinBE;
d = aMaxBE - aMinBE;
L_Ack = 2;
% creating filenames for saving data
fsuffix = strcat('_BE',num2str(aMinBE),'_',num2str(aMaxBE),'_L',num2str(minL),'_',num2str(maxL),'_N',num2str(minN),'_',num2str(maxN),'_M',num2str(M),'_R',num2str(R),'_T',num2str(tt));
fname_data = strcat('data/',date,fsuffix);
T = 10^tt; %nb of slots simulation runs
N = minN:stepN:maxN;
LL = minL:stepL:maxL; % Note: this range for L is kept from an older
% version for legacy. However, LL has to be scalar,
% otherwise, the code will not run properly. For
% running for vector LL, the code has to be modified.
%-------------------------------------------------------------------------
% Initializing variables
%-------------------------------------------------------------------------
% The following parameters are counted for node 1 only (reference node)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
nbBsuc = zeros(length(LL),length(N)); % total # slots spent in BO before a success (until t)
nbBcol = zeros(length(LL),length(N)); % total # slots spent in BO before a collision (until t)
nbBfail = zeros(length(LL),length(N)); % total # slots spent in BO before a failure (until t)
nbCCAsuc = zeros(length(LL),length(N)); % total # slots spent in CCA before a success (until t)
nbCCAcol = zeros(length(LL),length(N)); % total # slots spent in CCA before a collision (until t)
nbCCAfail = zeros(length(LL),length(N)); % total # slots spent in CCA before a failure (until t)
nbSuccess = zeros(length(LL),length(N)); % #slots in successful tx
nbCollision = zeros(length(LL),length(N)); % #slots in collision
nbCCA1 = zeros(length(LL),length(N)); % #slots in CCA1
nbCCA2 = zeros(length(LL),length(N)); % #slots in CCA2
nbFailure = zeros(length(LL),length(N)); % #packets dropped due to access procedure failure
nbDiscardR = zeros(length(LL), length(N)); % #discarded pkt after R retransmission
% variables for calculating y(i). i = number of nodes (L,N,i)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
nbCCA1_i_LN = zeros(length(LL),length(N),maxN); % ~(L,N,i): #slots exactly i nodes in CCA1 (in a network with N nodes and pkt size L)
nbCCA2_total_i_LN = zeros(length(LL),length(N),maxN); % #slots exactly i nodes in CCA2
nbCCA2_free_i_LN = zeros(length(LL),length(N),maxN); % #slots exactly i nodes in CCA2 and CCA2 successful
y_i_LN = zeros(length(LL),length(N),maxN); % access probability when exactly i nodes in CCA1
%network parameters (total of all nodes)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
nbTX_Net = zeros(length(LL),length(N)); % #slots in pkt tx (where at least one node is sending): this is per network
nbAck = zeros(length(LL),length(N)); % #slots in ACK tx
%-------------------------------------------------------------------------
for l = 1:length(LL)
nbBackoff_tmp = 0;
nbCCA_tmp = 0;
L = LL(l)
WW = 2.^min(aMinBE+[0:M],aMaxBE);
nBSN = [];
r_suc_total = zeros(size(N)); % #retx b4 suc (total over all t for node 1)
r_fail_total = zeros(size(N)); % #retx b4 fail (total over all t for node 1)
nbSuc_Ai = zeros(R+1,length(N)); % nbSuc_Ai(i,N) = #successes in i attempts of node 1
nbFail_Ai = zeros(R+1,length(N)); % nbFail_Ai(i,N) = #failures in i attempts of node 1
pkt_time_suc_total = zeros(size(N)); % #slots b4 suc (total over all t for node 1)
pkt_time_fail_total = zeros(size(N)); % #slots b4 fail (total over all t for node 1)
pkt_time_discardR_total = zeros(size(N)); % #slots b4 discardR (total over all t for node 1)
nbBackoff_tmp = 0; % temporary counter of #slots of node 1 in backoff
nbCCA_tmp = 0; % temporary counter of #slots of node 1 in CCA
nbCCA1BS = zeros(M+1,length(N)); % #slots in CCA1 at every backoff stage
nbCCA2BS = zeros(M+1,length(N)); % #slots in CCA2 at every backoff stage
nbSuccessBS = zeros(M+1,length(N)); % #Succesful tx from every backoff stage
nbCollisionBS = zeros(M+1,length(N)); % #Collisions from every backoff stage
% parameters to check the dependency between nodes. BS: Backoff Stage
BS12 = zeros(M+1, M+1,length(N)); % BS12(i,j,n) is the number of time slots nodes 1 and 2 have spent in BS's i and j respectively (and simultaneously) when there are N(n) nodes in the network
BS1 = zeros(M+1,length(N)); % BS12(i,j,n) is the number of time slots node 1 has spent in BS i when there are N(n) nodes in the network
BS2 = zeros(M+1,length(N)); % BS12(i,j,n) is the number of time slots node 2 has spent in BS i when there are N(n) nodes in the network
for n = 1:length(N) % run the network simulation for different network sizes
tic
% initializing parameters for all nodes of a network of N(n) nodes
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
NB = zeros(1,N(n)); % current backoff stage (start from 0)
CW = 2*ones(1,N(n)); % # CCAs left to perform
W = WW(1)*ones(1,N(n)); % all nodes in the first BS
nBS = zeros(M+1,N(n)); % nBS(i,j): # times node j has been in backoff stage i-1
nbBackoff_tmp = 0; % # backoffs of node 1 since the last success or failure
nbCCA_tmp = 0; % # CCAs of node 1 since the last success or failure
r = zeros(1,N(n)); % current # retransmissions done on a given pkt for each node
backoff(1:N(n))= floor(rand(1,N(n)).*W); % pick random backoff value for each node
busyForTx(1:N(n)) = 0; % # busy slots left for pkt tx
busyForAck(1:N(n)) = 0; % # busy slots left for ACK rx
Ack(1:N(n)) = 0; % total # slots spent in waiting for and receiving the ACK
collision(1:N(n)) = 0;
pkt_time = 0; % time spent in chain for the current pkt of node 1
% main loop: Running simulation for each slot
%------------------------------------------------------------------
for t = 1:T
pkt_time = pkt_time + 1;
BS12(NB(1)+1,NB(2)+1,n) = BS12(NB(1)+1,NB(2)+1,n) + 1; % ((busyFor(1) == 0)*(busyFor(2) == 0)); % when neither is transmitting
BS1(NB(1)+1,n) = BS1(NB(1)+1,n) + 1; % (busyFor(1) == 0); %increment when not transmitting
BS2(NB(2)+1,n) = BS2(NB(2)+1,n) + 1; % (busyFor(2) == 0);
% variables for calculating y(i)
CW_snapshot = CW; % CW status of all nodes at the beginning of the slot
BO_snapshot = backoff; % backoff status of nodes at the beginning of the slot
CCA1_not_counted = 1;
CCA2_total_not_counted = 1;
CCA2_free_not_counted = 1;
if (busyForTx(1:N(n)) == 0 & busyForAck(1:N(n)) == 0)
channel = 0; %channel idle - nobody is transmitting a pkt or an ACK
else
channel = 1; %channel busy
nbTX_Net(l,n) = nbTX_Net(l,n) + (sum(busyForTx)>0); %# slots channel busy for pkt tx
nbAck(l,n)= nbAck(l,n) + (sum(busyForAck)>0); %#slots channel busy for ACK tx
end
N_TX = nnz(busyForTx > 0); %number of nodes transmitting (CW(i)=0 means node i is in tx mode)
% updating each node
%%%%%%%%%%%%%%%%%%%%%%
for i = 1:N(n)
% Transmission
%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if busyForTx(i) > 0 % node i in tx mode: s(t) = -1
if (N_TX > 1) % some other node(s) also txing
nbCollision(l,n) = nbCollision(l,n)+ (i==1);
nbCollisionBS(NB(i)+1,n) = nbCollisionBS(NB(i)+1,n) + (i==1);
collision(i) = 1;
if (i == 1) & (busyForTx(i) == L)
nbBcol(l,n) = nbBcol(l,n) + nbBackoff_tmp;
nbBackoff_tmp = 0;
nbCCAcol(l,n) = nbCCAcol(l,n) + nbCCA_tmp;
nbCCA_tmp = 0;
end
else %only node i transmitting
nbSuccess(l,n) = nbSuccess(l,n) + (i==1);
nbSuccessBS(NB(i)+1,n) = nbSuccessBS(NB(i)+1,n) + (i==1);
if (i == 1) & (busyForTx(i) == L)
nbBsuc(l,n) = nbBsuc(l,n) + nbBackoff_tmp;
nbBackoff_tmp = 0;
nbCCAsuc(l,n) = nbCCAsuc(l,n) + nbCCA_tmp;
nbCCA_tmp = 0;
r_suc_total(n) = r_suc_total(n) + r(1);
nbSuc_Ai(r(1)+1, n) = nbSuc_Ai(r(1)+1, n) + 1;
pkt_time_suc_total(n) = pkt_time_suc_total(n) + pkt_time + L - 1;
end
end
busyForTx(i) = busyForTx(i) - 1;
if busyForTx(i) == 0 %node has finished its tx and waits for the ACK (it spends 3 slots in both case: success or collided tx)
Ack(i) = 3;
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
else %node i not in tx mode: s(t) >= 0
% Backoff
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if backoff(i) > 0 %node in BACKOFF
backoff(i) = backoff(i) - 1;
nbBackoff_tmp = nbBackoff_tmp + (i==1); % nb backoffs of node 1 since the last success or failure
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
else %backoff(i) == 0 --> CCA1 or CCA2 or ACK
if CW(i)==2 %CCA1
% CCA1
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
nbCCA1(l,n) = nbCCA1(l,n)+(i==1);
nbCCA1BS(NB(i)+1,n) = nbCCA1BS(NB(i)+1,n) + (i==1);
nbCCA_tmp = nbCCA_tmp + (i==1);
nBS(NB(i)+1,i) = nBS(NB(i)+1,i) + 1;
%for y(i) calculation
if CCA1_not_counted
nbNodesCCA1 = nnz(BO_snapshot(find(CW_snapshot == 2))==0); % # nodes performing CCA1
nbCCA1_i_LN(l,n,nbNodesCCA1) = nbCCA1_i_LN(l,n,nbNodesCCA1) + 1;
CCA1_not_counted = 0;
end
if channel == 0 %channel idle. No pkt or ACK transmission on the channel
CW(i)= CW(i)- 1;
else
CW(i)= 2;
NB(i) = NB(i)+ 1;
if NB(i) > M
nbFailure(l,n) = nbFailure(l,n) + (i==1);
NB(i) = 0;
if i == 1
nbBfail(l,n) = nbBfail(l,n)+nbBackoff_tmp;
nbBackoff_tmp = 0;
nbCCAfail(l,n) = nbCCAfail(l,n) + nbCCA_tmp;
pkt_time_fail_total = pkt_time_fail_total + pkt_time;
pkt_time = 0;
nbCCA_tmp = 0;
nbFail_Ai(r(1)+1, n) = nbFail_Ai(r(1)+1, n) + 1;
end
r(i) = 0; %reset r for the new pkt
end
W(i)= WW(NB(i)+1);
backoff(i) = floor(rand(1).*W(i));
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
elseif CW(i)==1 %CCA2
% CCA2
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
nbCCA2(l,n) = nbCCA2(l,n) + (i==1);
nbCCA2BS(NB(i)+1,n) = nbCCA2BS(NB(i)+1,n) + (i==1);
nbCCA_tmp = nbCCA_tmp + (i==1);
%for y(i) computation
if CCA2_total_not_counted
nbNodesCCA2 = nnz(CW_snapshot == 1);
nbCCA2_total_i_LN(l,n,nbNodesCCA2) = nbCCA2_total_i_LN(l,n,nbNodesCCA2) + 1;
CCA2_total_not_counted = 0;
end
if channel == 0
%for y(i) computation
if CCA2_free_not_counted
nbCCA2_free_i_LN(l,n,nbNodesCCA2) = nbCCA2_free_i_LN(l,n,nbNodesCCA2) + 1;
CCA2_free_not_counted = 0;
end
CW(i)= CW(i)- 1;
busyForTx(i) = L;
else
CW(i)= 2;
NB(i) = NB(i)+ 1;
if NB(i) > M
nbFailure(l,n) = nbFailure(l,n) + (i==1);
NB(i) = 0;
if i == 1
nbBfail(l,n) = nbBfail(l,n)+nbBackoff_tmp;
nbBackoff_tmp = 0;
nbCCAfail(l,n) = nbCCAfail(l,n) + nbCCA_tmp;
nbCCA_tmp = 0;
pkt_time_fail_total = pkt_time_fail_total + pkt_time;
pkt_time = 0;
nbFail_Ai(r(1)+1, n) = nbFail_Ai(r(1)+1, n) + 1;
end
r(i) = 0; %reset r for the new pkt
end
W(i)= WW(NB(i)+1);
backoff(i) = floor(rand(1).*W(i));
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
else %CW(i) = 0
% Ack wait/reception
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if Ack(i) == 3 % ACK
Ack(i) = Ack(i) - 1;
busyForAck(i) = L_Ack*(1-collision(i)); % if not in collision, receive ack in the next L_Ack slots
% (channel will be detected busy in the next slot)
else
Ack(i) = Ack(i) - 1;
busyForAck(i) = busyForAck(i) - (1-collision(i));
if Ack(i) == 0
r(i) = (r(i) + 1)*collision(i);
if r(i) > R
r(i) = 0;
if i == 1
nbDiscardR(l,n) = nbDiscardR(l,n) + 1; %# discarded pkt for collided retransmissions
pkt_time_discardR_total = pkt_time_discardR_total + pkt_time;
pkt_time = 0;
end
else
if (i == 1) & (collision(i) == 0)
pkt_time = 0;
end
end
% reset parameters for a retransmitted pkt or for a new pkt
NB(i) = 0;
CW(i) = 2;
W(i) = WW(NB(i)+1);
backoff(i)= floor(rand(1).*W(i));
collision(i) = 0;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
end
end
end
end
end
end
if t>T-200
if ((busyForAck(1) == 0)&(nbBackoff_tmp == 0))
TT(l,n) = t;
break
end
end
end
%------------------------------------------------------------------
nBSN = [nBSN,nBS(:,1)]; % the first row of nBS has # times
% node 1 has visited BS 0..M
N(n)
toc
if tt > 5
save(fname_data) % save data when it's worth it!
end
end
t_end = clock;
elapsed_minutes = etime(t_end,t_start)/60
alphaBS = (nbCCA1BS - nbCCA2BS)./nbCCA1BS;
betaBS = (nbCCA2BS - nbCollisionBS/L - nbSuccessBS/L)./nbCCA2BS;
end
N_LN = ones(length(LL),length(N))*diag(N); % size = LxN (legacy)
L_LN = diag(LL)*ones(length(LL),length(N)); %length(N) columns of LL (size = LxN) (legacy)
% Calculating parameters from simulation
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
b00LN = (nbSuccess./L_LN + nbCollision./L_LN + nbFailure)./TT; %might need to use floor() for small t
alphaLN = (nbCCA1 - nbCCA2)./nbCCA1;
betaLN = (nbCCA2 - nbCollision./L_LN - nbSuccess./L_LN)./nbCCA2;
phiLN = nbCCA1./TT;
nz_y = find(nbCCA1_i_LN); % eliminating the zero elements to avoid divide by zero in next line
y_i_LN(nz_y) = nbCCA2_free_i_LN(nz_y)./nbCCA1_i_LN(nz_y);
y_i_2D = reshape(y_i_LN,length(N),N(n))';
nbPtotalLN = nbSuccess./L_LN + nbFailure + nbDiscardR; % total # packets (P stands for packet)
nbPsucLN = nbSuccess./L_LN; % # successfully transmitted packets
nbAcolLN = nbCollision./L_LN; % #attempts that end in collision
nbPfailLN = nbFailure;
nbAttempts = nbPsucLN + nbPfailLN + nbAcolLN; % total # attempts
nbTXtotal = nbPsucLN + nbAcolLN; % total number of transmissions (# times we enter tx states)
% Collision, Transmission, Success probabilities: Pc, Ptx, Psuc
%%%%%%%%%%%%%%%%%%%%%%%%%%%%
tp_simLN = nbSuccess./TT;
Pf_simLN = nbPfailLN./nbAttempts; % fraction of failed attempts
PcNode_simLN = nbAcolLN./(nbAcolLN + nbPsucLN); % fraction of transmission attempts (of node 1) that end in collision
PsucNode_simLN = nbSuccess./TT; %per node
PtxNet_simLN = nbTX_Net./TT;
PcNet_simLN = 1-N_LN.*PsucNode_simLN./PtxNet_simLN; % fraction of transmission time of the NETWORK which is spent in collision
PtxNode_simLN = (nbSuccess + nbCollision)./TT;
Pdc_simLN = nbDiscardR./nbPtotalLN;
Pdf_simLN = nbFailure./nbPtotalLN; % fraction of failed pkt
Pd_simLN = Pdc_simLN + Pdf_simLN;
PcA_sim = nbAcolLN./nbAttempts; % = (1-Pf_simLN).*PcNode_simLN
% Network throughput
%%%%%%%%%%%%%%%%%%%%%%%%%%%%
tp_simLN = N_LN.*PsucNode_simLN;
% y
%%%%%%%%%%%%%%%%%%%%%%%%%%%%
yLN = (1-alphaLN).*(1-betaLN);
yLN_net_sim = sum(nbCCA2_free_i_LN,3)./sum(nbCCA1_i_LN,3); % y_* directly from simulation
yLN_node_sim = yLN; % y_o from simulation
% per packet
%%%%%%%%%%%%
mean_r_suc_sim = r_suc_total./nbPsucLN;
mean_delay_sim = pkt_time_suc_total./nbPsucLN;
Psuc_pkt_sim = nbPsucLN./nbPtotalLN; % 1 - Pd
% Delay calculations
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Mean # backoff and CCA per attempt (not per packet) from simulation
nbBtotal = nbBsuc+nbBcol+nbBfail;
mean_nbB_sim = nbBtotal./nbAttempts; % for the energy consumption
mean_nbBsuc_sim = nbBsuc./nbPsucLN; % for the delay calculation
mean_nbBcol_sim = nbBcol./nbAcolLN;
mean_nbBtx_sim = (nbBsuc + nbBcol)./(nbPsucLN + nbAcolLN);
mean_nbBf_sim = nbBfail./(nbPfailLN);
nbCCAtotal = nbCCAsuc+nbCCAcol+nbCCAfail;
mean_nbCCA_sim = nbCCAtotal./nbAttempts; % for the energy consumption
mean_nbCCAsuc_sim = nbCCAsuc./(nbPsucLN); % for the delay calculation
mean_nbCCAfail_sim = nbCCAfail./nbPfailLN;
mean_nbCCAcol_sim = nbCCAcol./nbAcolLN;
mean_nbCCAtx_sim = (nbCCAsuc + nbCCAcol)./(nbPsucLN + nbAcolLN);
mean_delay_formula_sim = (mean_nbCCAtx_sim + mean_nbBtx_sim + L + 3).*(mean_r_suc_sim + 1) - 3;
% Power consumption
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
V_DD = 3;
t_bp = .32e-3;
W_tx = 26.9e-3*V_DD; % only in TX states
W_rx = 26.7e-3*V_DD; % in CCA states and the two last ACK states
W_id = 0.5e-6*V_DD; % in BO states and the first ACK state
A = 80/(.32e-3); % #bits per BP
EnergyLN_sim = (nbBtotal+nbTXtotal)*W_id + (nbCCAtotal+2*nbTXtotal)*W_rx + nbTXtotal.*L_LN.*W_tx;
PowerLN_sim = EnergyLN_sim./TT;
% per attempt probabilities
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
nbCol_Ai = zeros(R+1,length(N));
for i = 1:R+1 % #collisions happened in attempt i
nbCol_Ai(i,:) = (sum((nbSuc_Ai(i+1:end,:)) + nbFail_Ai(i+1:end,:),1)+nbDiscardR);
end
for i = 1:R+1 % #pkts who reach attempt i
nbAttempt_i(i,:) = (sum((nbSuc_Ai(i:end,:)) + nbFail_Ai(i:end,:),1)+nbDiscardR);
end
PcAi_sim = nbCol_Ai./nbAttempt_i; % prob that attempt i ends in COL
Pf_Ai = nbFail_Ai./nbAttempt_i; % prob that attempt i ends in FAIL ###
Psuc_Ai = nbSuc_Ai./nbAttempt_i; % prob that attempt i ends in SUC ###
PcA1_to_i_sim = nbCol_Ai*diag(1./nbPtotalLN); % = prod(PcAi_sim(1:i,:),1) ###
if tt > 5
save(fname_data)
end