📄 action.m
字号:
if bdebug, disp(['wait_for_channel @ node ' num2str(i)]); end
% if mac_status(i) == 0
% % Reset by timeout_rreq after many RREQ retries
% if ddebug, disp(['wait_for_channel: node ' num2str(i) 'mac_status reset because so many RREQ retries at network layer']); end
% return;
% end
if node(i, 4) == 0 & carrier_sense(i) == 0
% question: I want to transmit, but have to capture from many neighbors
% the node is idle and the channel is free, can backoff now
if backoff_counter(i) > 0 % resume the backoff
newevent = event;
newevent.instant = t + slot_time;
newevent.type = 'backoff';
newevent.node = i;
NewEvents = [NewEvents; newevent]; clear newevent;
else % start from DIFS first
newevent = event;
newevent.instant = t + DIFS;
newevent.type = 'backoff_start';
newevent.node = i;
NewEvents = [NewEvents; newevent]; clear newevent;
end
else
% the node is not idle; must be receiving...wait until this receiving is finished
% or the channel is not free; wait until the channel is free
newevent = event;
newevent.instant = t + cca_time;
newevent.type = 'wait_for_channel';
newevent.node = i;
NewEvents = [NewEvents; newevent]; clear newevent;
end
case 'backoff_start' % after DIFS, start backoff
t = event.instant;
i = event.node;
j = event.pkt.rv;
if bdebug, disp(['backoff_start @ node ' num2str(i)]); end
if node(i, 4) == 0 & carrier_sense(i) == 0
% the node is still idle and the channel is free, start backoff
% question: what if the channel was busy during this DIFS period?
backoff_attempt(i) = 0;
temp = min(backoff_attempt(i)+CW_min,CW_max);
backoff_counter(i) = floor((2^temp-1)*rand);
newevent = event;
newevent.instant = t + slot_time;
newevent.type = 'backoff';
newevent.node = i;
NewEvents = [NewEvents; newevent]; clear newevent;
else
% channel becomes busy during DIFS, wait until the channel is free
newevent = event;
newevent.instant = t + cca_time;
newevent.type = 'wait_for_channel';
newevent.node = i;
NewEvents = [NewEvents; newevent]; clear newevent;
end
case 'backoff'
t = event.instant;
i = event.node;
j = event.pkt.rv;
if bdebug, disp(['backoff @ node ' num2str(i)]); end
if node(i, 4) == 0 & carrier_sense(i) == 0
% the node is still idle and the channel is free, continue backoff
if backoff_counter(i) > 1
backoff_counter(i) = backoff_counter(i) - 1;
newevent = event;
newevent.instant = t + slot_time;
newevent.type = 'backoff';
newevent.node = i;
NewEvents = [NewEvents; newevent]; clear newevent;
else % ready to send the packet
backoff_counter(i) = 0; % reset counter for next use
newevent = event;
newevent.instant = t;
newevent.type = 'send_phy';
newevent.node = i;
NewEvents = [NewEvents; newevent];
% txtime = tx_time(newevent.pkt);
clear newevent;
% mac_queue will be taken care of after really send this packet in 'send_phy_finish'
% if j == 0 % broadcast: the real data is sent here
% % we can send the next packet from mac_queue now
% if ~isempty(mac_queue(i).list)
% % more packets are waiting to be sent
% newevent = mac_queue(i).list(1);
% mac_queue(i).list(1) = [];
% newevent.instant = t + txtime + cca_time; % question: should cca_time or other be used here?
% newevent.type = 'wait_for_channel';
% newevent.node = i;
% NewEvents = [NewEvents; newevent]; clear newevent;
% else
% % will reset in 'send_phy_finish'
% % mac_status(i) = 0;
% end
% else
% % unicast: the RTS is sent here, will wait for CTS or timeout_rts
% % do nothing here
% end
end
else % channel becomes busy during backoff count-down
if backoff_counter(i) > 1
backoff_counter(i) = backoff_counter(i) - 1;
else
% start a new backoff counter when count-down is zero
backoff_attempt(i) = backoff_attempt(i) + 1;
temp = min(backoff_attempt(i)+CW_min,CW_max);
backoff_counter(i) = floor((2^temp-1)*rand);
end
newevent = event;
newevent.instant = t + cca_time;
newevent.type = 'wait_for_channel';
newevent.node = i;
NewEvents = [NewEvents; newevent]; clear newevent;
end
case 'timeout_rts'
t = event.instant;
i = event.node;
j = event.pkt.rv;
if adebug, disp(['timeout_rts @ node ' num2str(i)]); end
if pending_id(i) == event.pkt.id % not acknowledged yet, retransmit
if cdebug, disp(['timeout_rts: node ' num2str(i) ' pending_id=' num2str(pending_id(i)) ' event_id=' num2str(event.pkt.id)]); end
retransmit(i) = retransmit(i) + 1;
if retransmit(i) > max_retries
% so many retries, drop the packet
if cdebug, disp(['timeout_rts: node ' num2str(i) ' has retried so many times to transmit RTS']); end
retransmit(i) = 0;
pending_id(i) = 0;
% question: what if there are waiting packets in mac_queue?
% answer: should send them anyway as if the current packet is done.
% similar to the the operation when ACK is received
if ~isempty(mac_queue(i).list)
% more packets are waiting to be sent
% newevent.instant = t + turnaround_time; % switch from receive to transmit
mac_status(i) = 1;
newevent = mac_queue(i).list(1);
mac_queue(i).list(1) = [];
newevent.instant = t + cca_time; % question: cca_time or other
newevent.type = 'wait_for_channel';
newevent.node = i;
% packet setup is already done in 'send_mac' before put into the mac_queue
NewEvents = [NewEvents; newevent]; clear newevent;
else
% cannot send RTS successfully, reset MAC layer
mac_status(i) = 0;
end
return;
end
if adebug, disp(['timeout_rts: node ' num2str(i) ' to retransmit RTS']); end
% retransmit the RTS
newevent = event;
newevent.instant = t + cca_time; % check channel status
newevent.type = 'wait_for_channel';
newevent.node = i;
NewEvents = [NewEvents; newevent]; clear newevent;
else
% if pending_id(i) ~= 0 & ddebug, disp(['timeout_rts at node ' num2str(i) ' pending id=' num2str(pending_id(i)) ' does not match the waiting RTS id=' num2str(event.pkt.id)]); end
end
case 'timeout_data'
t = event.instant;
i = event.node;
j = event.pkt.rv;
if adebug, disp(['timeout_data @ node ' num2str(i)]); end
% if pending_id(i) == event.pkt.id % not acknowledged yet
% if adebug, disp(['timeout_data: node ' num2str(i) ' failed to transmit DATA, go back to transmit RTS']); end
% % remove the pending id for DATA
% pending_id(i) = 0;
% retransmit(i) = 0;
% % go back to send RTS
% newevent = event;
% newevent.instant = t + cca_time; % check channel status
% newevent.type = 'wait_for_channel';
% newevent.node = i;
% newevent.pkt.type = 'data';
% newevent.pkt.nav = SIFS + cts_tx_time + SIFS + tx_time(newevent.pkt) + SIFS + ack_tx_time;
% newevent.pkt.type = 'rts';
% % create a new id for the new RTS
% newevent.pkt.id = new_id(i);
% NewEvents = [NewEvents; newevent]; clear newevent;
% end
if pending_id(i) == event.pkt.id % not acknowledged yet
if cdebug, disp(['timeout_data: node ' num2str(i) ' pending_id=' num2str(pending_id(i)) ' event_id=' num2str(event.pkt.id)]); end
retransmit(i) = retransmit(i) + 1;
if retransmit(i) > max_retries
% so many retries, drop the data packet
if cdebug, disp(['timeout_data: node ' num2str(i) ' has retried so many times to transmit DATA']); end
retransmit(i) = 0;
pending_id(i) = 0;
if ~isempty(mac_queue(i).list)
% more packets are waiting to be sent
mac_status(i) = 1;
newevent = mac_queue(i).list(1);
mac_queue(i).list(1) = [];
newevent.instant = t + cca_time; % question: cca_time or other
newevent.type = 'wait_for_channel';
newevent.node = i;
NewEvents = [NewEvents; newevent]; clear newevent;
else
% Cannot send DATA successfully, reset MAC layer
mac_status(i) = 0;
end
return;
end
if adebug, disp(['timeout_data: node ' num2str(i) ' to retransmit DATA']); end
% retransmit the DATA
newevent = event;
newevent.instant = t + cca_time; % check channel status
newevent.type = 'wait_for_channel';
newevent.node = i;
% newevent.pkt.type = 'data';
newevent.pkt.nav = SIFS + ack_tx_time; % necessary for retransmission because the initial DATA has NAV=0
NewEvents = [NewEvents; newevent]; clear newevent;
end
case 'recv_mac'
t = event.instant;
i = event.pkt.tx;
j = event.node;
if adebug, disp(['recv_mac @ node ' num2str(j)]); end
if event.pkt.rv == 0 & strcmp(event.pkt.type, 'data') == 0
% broadcast but not data packet
error(['recv_mac: node ' num2str(j) ' receives a broadcast packet with a wrong type: ' event.pkt.type]);
end
if j == i
% I myself sent this packet, no action
return;
end
switch event.pkt.type
case 'rts'
% send back a CTS
newevent = event;
newevent.instant = t + SIFS;
newevent.type = 'send_phy';
newevent.node = j;
% keep the data size, rate, and id as RTS packet
newevent.pkt.type = 'cts';
newevent.pkt.tx=j;
newevent.pkt.rv=i;
newevent.pkt.nav=event.pkt.nav - SIFS - cts_tx_time;
NewEvents = [NewEvents; newevent]; clear newevent;
case 'cts'
% remove pending id for RTS
if pending_id(j) ~= event.pkt.id
if ddebug, disp(['the received CTS id ' num2str(event.pkt.id) ' does not match the pending RTS id ' num2str(pending_id(j))]); end
% probably this CTS is in response to an earlier RTS,
% but I have retransmitted a new RTS which is replied
% already or I have retransmitted so many times and given up
% so we just ignore this CTS.
return;
end
pending_id(j) = 0;
retransmit(j) = 0;
% send DATA
newevent = event;
newevent.instant = t + SIFS;
newevent.type = 'send_phy';
newevent.node = j;
% keep the data size and rate as before
% newevent.pkt.ttl = 1;
newevent.pkt.type = 'data';
newevent.pkt.tx=j;
newevent.pkt.rv=i;
% creat a new id for the data packet
newevent.pkt.id = new_id(j);
newevent.pkt.nav = 0; % not necessary because RTS already did so
NewEvents = [NewEvents; newevent]; clear newevent;
case 'data'
% should check that this is not a duplicated or out-of-order packet
if event.pkt.rv ~= 0 % send ACK if not broadcast
% send back an ACK
newevent = event;
newevent.instant = t + SIFS;
newevent.type = 'send_phy';
newevent.node = j;
% keep the data size, rate, and id the same as DATA packet
newevent.pkt.type = 'ack';
newevent.pkt.tx=j;
newevent.pkt.rv=i;
newevent.pkt.nav=0; % not necessary because CTS already did so
NewEvents = [NewEvents; newevent]; clear newevent;
end
% send data up to network layer
newevent = event;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -