% 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