📄 action.m
字号:
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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -