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