代码各种不懂,求各位大虾指点
function [NewEvents] = action(event, log_file)% debug:
% TTL is determined at network layer only
% one way transmission received, reverse transmission fails, why?
% mainly because randomness in the 'shadowing' model: solved...same distance generates same random number
% friis model works fine
% tworay model is mostly the same as friis because crossover distance = 100 m
% freq should be 2.4G instead of 2.4M, white_noise_variance is changed correspondingly
% Duplicated packets due to early time out and retransmission: this is ok, just provide a larger timeout
% queue waiting problem: net_queue is actually always empty, all NET packets stack at mac_queue
% mac_queue is accompanied by mac_status
% Question 1: how to decide the priority of broadcast, unicast transmission and receptioin?
% to add virtual carrier sense: done
% to add RTS-CTS: done
% to add ad hoc routing: done
% to add application layer actions:
% to add figures or animations to show network and traffic change: not critical
global adebug bdebug;
global Gt Gr freq L ht hr pathLossExp std_db d0 rmodel;
global cs_threshold white_noise_variance rv_threshold rv_threshold_delta;
global slot_time CW_min CW_max turnaround_time max_retries SIFS DIFS cca_time basic_rate default_power;
global max_size_mac_body size_mac_header size_rts size_cts size_ack size_plcp;
global n node Event_list;
global packet_id retransmit pending_id mac_queue backoff_attmpt backoff_counter backoff_attempt;
global nav;
global ack_tx_time cts_tx_time rts_tx_time;
global default_rate default_ttl;
global size_rreq size_rrep;
global rreq_timeout net_queue net_pending net_max_retries;
global rrep_table; % id, route, metric
global bcast_table;
global mac_status;
global adebug bdebug cdebug ddebug;
global rreq_out rreq_in rreq_forward;
global rreq_out_crosslayer rreq_in_crosslayer rreq_forward_crosslayer;
global rrep_out rrep_in rrep_forward;
global rrep_out_crosslayer rrep_in_crosslayer rrep_forward_crosslayer rrep_destination_crosslayer;
NewEvents = [];
switch event.type
case 'send_phy'
t = event.instant;
i = event.node;
j = event.pkt.rv;
if adebug, disp(['send_phy at time ' num2str(t) ' node ' num2str(i) ' will send a packet to node ' num2str(j)]); end
txtime = tx_time(event.pkt);
if node(i, 4) == 0 & (nav(i).start > (t+txtime) | nav(i).end < t) % idle and no nav
node(i, 3) = event.pkt.power;
node(i, 4) = 1; % switch to transmit mode, assume turnaround time is zero
% set up the receiver
if j == 0 % broadcast from node i
for k=1:n
% due to broadcast nature in wireless channel, every idle node may capture/sense this transmission
if node(k, 4)~=0 | k==i, continue; end
if overlap(t, t+txtime, nav(k).start, nav(k).end), continue; end
node(k, 4) = 2; % receiver switches to receiving mode
newevent = event;
newevent.instant = t + txtime;
newevent.type = 'recv_phy';
newevent.node = k;
NewEvents = [NewEvents; newevent]; clear newevent;
end
% when there is no node to receive this broadcast, still send it.
% because I do not know if any node will respond, but actually node node will respond.
% if length(NewEvents) <= 0
% if ddebug, disp(['send_phy: node ' num2str(i) ' broadcasts to no nodes']); end
% newevent = event;
% newevent.instant = t;
% newevent.type = 'send_phy_finish';
% newevent.node = i;
% NewEvents = [NewEvents; newevent]; clear newevent;
% return;
% end
else % unicast from i to j
if node(j, 4) ~= 0 | overlap(t, t+txtime, nav(j).start, nav(j).end)
if ddebug, disp(['send_phy: receiving node ' num2str(j) ' is not ready to receive from node ' num2str(i)]); end
% At physical layer, I cannot synchronize with the receiver, so I know I do not need to actually transmit?
% We sill transmit this packet, but no actual reception.
% newevent = event;
% newevent.instant = t;
% newevent.type = 'send_phy_finish';
% newevent.node = i;
% NewEvents = [NewEvents; newevent]; clear newevent;
% return;
else
node(j, 4) = 2; % receiver is switched to receiving mode
newevent = event;
newevent.instant = t + txtime;
newevent.type = 'recv_phy';
newevent.node = j;
NewEvents = [NewEvents; newevent]; clear newevent;
end
for k=1:n
% due to broadcast nature in wireless channel, every idle node may capture/sense this transmission
if node(k, 4)~=0 | k==i | k==j, continue; end
if overlap(t, t+txtime, nav(k).start, nav(k).end), continue; end
node(k, 4) = 2; % receiver switches to receiving mode
newevent = event;
newevent.instant = t + txtime;
newevent.type = 'recv_phy';
newevent.node = k;
NewEvents = [NewEvents; newevent]; clear newevent;
end
end
% setup the transmitter
newevent = event;
newevent.instant = t + txtime + eps;
newevent.type = 'send_phy_finish';
newevent.node = i;
NewEvents = [NewEvents; newevent]; clear newevent;
if strcmp(event.pkt.type, 'rts')
% set timeout timer for RTS
newevent = event;
newevent.instant = t + (txtime + SIFS + cts_tx_time) * 2; % question: how to choose this timeout limit?
newevent.type = 'timeout_rts';
newevent.node = i;
NewEvents = [NewEvents; newevent]; clear newevent;
if retransmit(i) <= 0 & pending_id(i) > 0
error(['send_phy: node ' num2str(i) ' there is already a pending packet, cannot send a new RTS packet']);
end
pending_id(i) = event.pkt.id;
end
if strcmp(event.pkt.type, 'data') & j ~= 0
% set timeout timer for DATA
newevent = event;
newevent.instant = t + (txtime + SIFS + ack_tx_time) * 2; % double check
newevent.type = 'timeout_data';
newevent.node = i;
NewEvents = [NewEvents; newevent]; clear newevent;
if retransmit(i) <= 0 & pending_id(i) > 0
error(['send_phy: node ' num2str(i) ' there is already a pending packet, cannot send a new DATA packet']);
end
pending_id(i) = event.pkt.id;
end
else % radio hardware is not idle or nav block
if adebug, disp(['send_phy at time ' num2str(t) ' node ' num2str(i) ' is not ready to send a packet to node ' num2str(j)]); end
if adebug, disp(['--- node(i, 4)=' num2str(node(i, 4)) 'nav.start=' num2str(nav(i).start) 'nav.end=' num2str(nav(i).end)]); end
% Since the node status is already checked at MAC layer, it must be due to NAV virtual carrier sense
% I am a hiddent node: physical carrier sense is okay, but blocked by virtual carrier sense
% I should go back to MAC and try later.
newevent = event;
newevent.instant = t + cca_time;
newevent.type = 'wait_for_channel';
newevent.node = i;
NewEvents = [NewEvents; newevent]; clear newevent;
% Drop the packet, and try next MAC packet if any
% 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: should cca_time or other be used here?
% newevent.type = 'wait_for_channel';
% newevent.node = i;
% NewEvents = [NewEvents; newevent]; clear newevent;
% else
% mac_status(i) = 0;
% end
end
case 'send_phy_finish'
t = event.instant;
i = event.node;
j = event.pkt.rv;
if bdebug, disp(['send_phy_finish @ node ' num2str(i)]); end
if node(i, 4) ~= 1
error(['send_phy_finish: node ' num2str(i) ' should be in transmission mode']);
end
node(i, 4) = 0; % after all receivings, go back to idle
node(i, 3) = 0;
if j==0 % | strcmp(event.pkt.type, 'ack')
% finished broadcast % or finished RTS-CTS-DATA-ACK for unicast
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: should cca_time or other be used here?
newevent.type = 'wait_for_channel';
newevent.node = i;
NewEvents = [NewEvents; newevent]; clear newevent;
else
mac_status(i) = 0;
end
end
case 'recv_phy'
t = event.instant;
i = event.pkt.tx;
j = event.node;
if bdebug, disp(['recv_phy @ node ' num2str(j)]); end
if node(j, 4) ~= 2
error(['recv_phy: node ' num2str(j) ' is not in receive mode']);
end
node(j, 4) = 0; % receiver switches back to idle mode
if t > nav(j).start & t < nav(j).end
% this has already been checked when sending
% but nav may be changed during transmission, so double check
if ddebug, disp(['recv_phy: packet virtual collision at node ' num2str(j)]); end
% just drop the packet
else
[pr, snr] = recv_phy(i, j, rmodel);
% disp(['recv_phy: node ' num2str(i) ' to node ' num2str(j) ' with snr= ' num2str(snr) ' and distance=' num2str(topo_dist(i, j))]);
t1 = rv_threshold_delta;
if snr >= (rv_threshold+t1)
probability_receive = 1;
elseif snr < (rv_threshold-t1)
probability_receive = 0;
elseif rand <= (snr-(rv_threshold-t1))/(t1+t1)
probability_receive = 1;
else
probability_receive = 0;
end
if probability_receive
if event.pkt.rv == 0 | event.pkt.rv == j % broadcast or unicast to this receiver
% TTL is taken care of at network layer
% event.pkt.ttl = event.pkt.ttl - 1;
% if event.pkt.ttl < 0
% if adebug, disp(['recv_phy: TTL from node ' num2str(i) ' to node ' num2str(j) ' is negative, drop the packet']); end
% return;
% end
% there is already a MAC layer packet waiting for transmission, but this incoming packet should be
% received first, no futher receiving is possible (see send_phy)
% if mac_status(j)
% if adebug, disp(['recv_phy: node ' num2str(j) ' is waiting to transmit, so cannot receive']); end
newevent = event;
newevent.instant = t;
newevent.type = 'recv_mac';
newevent.node = j;
NewEvents = [NewEvents; newevent]; clear newevent;
elseif event.pkt.nav > 0 % this packet is not for me, but use its nav
if nav(j).start < t
nav(j).start = t;
end
if nav(j).end < (t+event.pkt.nav)
% question: debug
nav(j).end = t + event.pkt.nav;
end
end
else
if bdebug, disp(['recv_phy: packet from node ' num2str(i) ' cannot be successfully received at node' num2str(j)]); end
end
end
case 'send_mac'
t = event.instant;
i = event.node;
j = event.pkt.rv;
if bdebug, disp(['send_mac: node ' num2str(i) ' to send to node ' num2str(j) ' isempty(mac_queue)=' num2str(isempty(mac_queue(i).list)) ' mac_status=' num2str(mac_status(i))]); end
event.pkt.id = new_id(i);
event.pkt.type = 'data'; % used in function call of 'tx_time'
% the tx_time should be the same as in 'send_phy'
event.pkt.nav = SIFS + cts_tx_time + SIFS + tx_time(event.pkt) + SIFS + ack_tx_time;
% if ddebug, disp(['send_mac node ' num2str(i) ' will reserve NAV=' num2str(event.pkt.nav)]); end
if j ~= 0
% for unicast, RTS should be sent first
event.pkt.type = 'rts';
end
% keep the data body size and rate for transmitting data later
if ~isempty(mac_queue(i).list) & ~mac_status(i)
error(['send_mac: node ' num2str(i) ' channel is free, but there is still packets waiting at MAC...this should not happen']);
end
if ~isempty(mac_queue(i).list) | mac_status(i)
% old packets are waiting to be sent, just wait behind them
% or one packet is being transmitted at MAC layer, just wait in the MAC queue
mac_queue(i).list = [mac_queue(i).list event];
else
mac_status(i) = 1;
% newevent.instant = t + turnaround_time; % swith to transmit
newevent = event;
newevent.instant = t + cca_time; % check channel status
newevent.type = 'wait_for_channel';
newevent.node = i;
NewEvents = [NewEvents; newevent]; clear newevent;
end
case 'wait_for_channel'
t = event.instant;
i = event.node;
j = event.pkt.rv;
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;