📄 action.m
字号:
% Make sure the ACK is sent out before processing this data packet in
% the upper layers because the upper layers may immediately
% send more packets upon receiving this data packet.
if event.pkt.rv ~= 0,
newevent.instant = t + SIFS + ack_tx_time + 2*eps;
else
newevent.instant = t + 2*eps;
end
newevent.type = 'recv_net';
newevent.node = j;
NewEvents = [NewEvents; newevent]; clear newevent;
case 'ack'
% make sure the acknowledged packet is the just sent DATA packet
if pending_id(j) ~= event.pkt.id
if ddebug, disp(['the received ACK id=' num2str(event.pkt.id) ' does not match the pending DATA id=' num2str(pending_id(j))]); end
% probably this is a duplicated ACK (same reason as the above CTS case)
return;
end
% remove pending id for DATA
pending_id(j) = 0;
retransmit(j) = 0;
if ~isempty(mac_queue(j).list)
% more packets are waiting to be sent
% newevent.instant = t + turnaround_time; % switch from receive to transmit
% if ddebug, disp('recv_mac: after receiving ACK, take the next packet from mac_queue'); end
mac_status(j) = 1;
newevent = mac_queue(j).list(1);
mac_queue(j).list(1) = [];
newevent.instant = t + cca_time;
newevent.type = 'wait_for_channel';
newevent.node = j;
% the packet setup is already done in 'send_mac'
NewEvents = [NewEvents; newevent]; clear newevent;
else
mac_status(j) = 0;
end
otherwise
disp(['recv_mac: Undefined mac packet type: ' event.pkt.type]);
end
case 'send_net'
% event provides net.dst, net.src, net.size
t = event.instant;
i = event.node;
j = event.net.dst;
if adebug, disp(['send_net @ node ' num2str(i)]); end
% net_queue
if ~isempty(net_queue(i).list)
% this is redundant; net_queue is always empty
% old packets are waiting to be sent, just wait behind them
% if cdebug, disp(['time ' num2str(t) ' node ' num2str(i) ' queue a packet to node ' num2str(j)]); end
net_queue(i).list = [net_queue(i).list event];
else
newevent = event;
newevent.type = 'send_net2';
NewEvents = [NewEvents; newevent]; clear newevent;
end
case 'send_net2'
t = event.instant;
i = event.node;
j = event.net.dst;
if adebug, disp(['send_net2 @ node ' num2str(i)]); end
% if ddebug, disp(['send_net2: time ' num2str(t) ' node ' num2str(i) ' starts to send a packet to node ' num2str(j)]); end
if j == 0 % broadcast
newevent = event;
newevent.instant = t;
newevent.type = 'send_mac';
newevent.node = i;
newevent.net.type = 'data';
newevent.net.id = new_id(i);
newevent.net.route = [];
newevent.net.metric = 0;
newevent.pkt.tx=i; % or event.net.src
newevent.pkt.rv=0;
newevent.pkt.type='data';
newevent.pkt.size=event.net.size; % assume no header in network layer
% if event.pkt.ttl <= 0, newevent.pkt.ttl = default_ttl; end
% if event.pkt.rate <= 0, newevent.pkt.rate=default_rate; end
% if event.pkt.power <= 0, newevent.pkt.power=default_power; end
newevent.pkt.ttl = default_ttl;
newevent.pkt.rate=default_rate;
newevent.pkt.power=default_power;
newevent.pkt.id=0;
newevent.pkt.nav=0;
NewEvents = [NewEvents; newevent]; clear newevent;
else % unicast: find the route by RREP-RREQ
% assume no neighbor table, find route even dst. is in the neighborhood
% assume no routing table, RREP will contain whole route
newevent = event;
newevent.instant = t;
newevent.type = 'send_mac';
newevent.node = i;
newevent.net.type = 'rreq';
rreq_out(i) = rreq_out(i) + 1;
if strcmp(newevent.app.type, 'crosslayer_searching')
rreq_out_crosslayer(i) = rreq_out_crosslayer(i) + 1;
end
% if ddebug, disp(['rreq_out(' num2str(i) ')=' num2str(rreq_out(i))]); end
newevent.net.id = new_id(i);
newevent.net.route = [i];
newevent.net.metric = 0; % no use for now
newevent.pkt.tx=i; % or event.net.src
newevent.pkt.rv=0; % broadcast RREQ
newevent.pkt.type='data';
newevent.pkt.size=size_rreq;
% if event.pkt.ttl <= 0, newevent.pkt.ttl = default_ttl; end
% if event.pkt.rate <= 0, newevent.pkt.rate=default_rate; end
% if event.pkt.power <= 0, newevent.pkt.power=default_power; end
newevent.pkt.ttl = default_ttl;
newevent.pkt.rate=default_rate;
newevent.pkt.power=default_power;
newevent.pkt.id=0;
newevent.pkt.nav=0;
NewEvents = [NewEvents; newevent];
% set timeout timer for RREQ
newevent.instant = t + rreq_timeout; % question: how large should this timeout be?
newevent.type = 'timeout_rreq';
NewEvents = [NewEvents; newevent];
net_pending(i).id = [net_pending(i).id newevent.net.id]; % save the id of pending RREQ
net_pending(i).retransmit = [net_pending(i).retransmit 0];
clear newevent;
end
case 'timeout_rreq'
t = event.instant;
i = event.node;
j = event.net.dst;
if bdebug, disp(['timeout_rreq @ node ' num2str(i)]); end
temp = find(net_pending(i).id == event.net.id);
if isempty(temp)
% The RREQ is already acknowledged and is not pending anymore, do nothing
return;
end
if length(temp) > 1
error(['timeout_rreq: node ' num2str(i) ' has more than one pending RREQs with id=' num2str(event.net.id)]);
end
% The RREQ is not acknowledged yet by an RREP
if ddebug, disp(['timeout_rreq: at time: ' num2str(t) ' node ' num2str(i) ' pending RREQ id=' num2str(net_pending(i).id(temp))]); end
net_pending(i).retransmit(temp) = net_pending(i).retransmit(temp) + 1;
if net_pending(i).retransmit(temp) > net_max_retries
% so many retries, drop the RREQ
% An RREP may come later, will just ignore
if ddebug, disp(['timeout_rreq: node ' num2str(i) ' has retried so many times to transmit RREQ']); end
net_pending(i).id(temp) = [];
net_pending(i).retransmit(temp) = [];
% Should take care of MAC layer queue
% 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 RREQ successfully, reset MAC layer
% mac_status(i) = 0;
% end
if ~isempty(net_queue(i).list)
% this is redundant, net_queue is always empty
% more packets are waiting to be sent
error(['timeout_rreq: node ' num2str(i) ' have a non-empty network layer queue']);
newevent = net_queue(i).list(1);
net_queue(i).list(1) = [];
newevent.instant = t;
newevent.type = 'send_net2';
NewEvents = [NewEvents; newevent]; clear newevent;
end
return;
end
if adebug, disp(['timeout_rreq: node ' num2str(i) ' to retransmit RREQ']); end
% retransmit the RREQ
newevent = event;
newevent.instant = t;
newevent.type = 'send_mac';
newevent.net.id = new_id(i); % question: do we need a new id for this retransmission? answer: yes, for bcast_table
net_pending(i).id(temp) = newevent.net.id;
rreq_out(i) = rreq_out(i) + 1;
if strcmp(newevent.app.type, 'crosslayer_searching')
rreq_out_crosslayer(i) = rreq_out_crosslayer(i) + 1;
end
NewEvents = [NewEvents; newevent];
% set timeout timer for the retransmitted RREQ
newevent.instant = t + rreq_timeout; % question: same as above
newevent.type = 'timeout_rreq';
NewEvents = [NewEvents; newevent];
net_pending(i).id(temp) = newevent.net.id; % save the new id of the pending RREQ
clear newevent;
case 'recv_net'
t = event.instant;
i = event.net.src;
j = event.node;
if bdebug, disp(['time ' num2str(t) ' recv_net @ node ' num2str(j)]); end
% take care of TTL at network layer
event.pkt.ttl = event.pkt.ttl - 1;
if event.pkt.ttl < 0
if bdebug, disp(['recv_net: TTL from node ' num2str(i) ' to ' num2str(j) ' is negative, drop the packet']); end
return;
end
if j == i | j == event.pkt.tx
% I myself sent this packet, no action
return;
end
% if cdebug, disp(['time ' num2str(t) 'node ' num2str(event.pkt.tx) ' -> node ' num2str(j) ' with type ' event.net.type]); end
switch event.net.type
case 'rreq'
rreq_in(j) = rreq_in(j) + 1;
if strcmp(event.app.type, 'crosslayer_searching')
rreq_in_crosslayer(j) = rreq_in_crosslayer(j) + 1;
end
if sum(ismember(event.net.route, j))
% I am already in the found route
return;
end
event.net.route = [event.net.route j];
if j == event.net.dst
% I am the destination of this RREQ: send RREP back
% check if I have already replied to the same RREQ
% if ~isempty(rrep_table) & sum(ismember(rrep_table, [i event.net.id], 'rows'))
% we currently use: rrep_table.id, rrep_table.metric, rrep_table.route
send_rrep = -1;
if isempty(rrep_table(j).list)
k = 1;
send_rrep = 1;
else
% rrep_table is not empty
for k=1:length(rrep_table(j).list)
if rrep_table(j).list(k).route(1)==i
% find a early saved RREQ from the same src
% assume this is the only saved RREQ from the same src
if rrep_table(j).list(k).id < event.net.id
% I replied to an older RREQ: take the new one and reply
send_rrep = 1;
elseif rrep_table(j).list(k).id == event.net.id
% I replied to the same RREQ: should I reply to again?
if event.net.metric < rrep_table(j).list(k).metric
% metric: the samller the better
% This is a better route, take it and reply
send_rrep = 1;
else
% not a better route: ignore
send_rrep = 0;
end
else
% I replied to a newer RREQ: ignore
send_rrep = 0;
end
break;
end
end
end
if send_rrep ~= 0
rrep_out(j) = rrep_out(j) + 1;
if strcmp(event.app.type, 'crosslayer_searching')
rrep_out_crosslayer(j) = rrep_out_crosslayer(j) + 1;
end
if send_rrep < 0
% no early saved RREQ from this src: add one
k = length(rrep_table(j).list) + 1; % same as: k = k + 1;
end
rrep_table(j).list(k).id = event.net.id;
rrep_table(j).list(k).metric = event.net.metric;
rrep_table(j).list(k).route = event.net.route;
newevent = event;
newevent.instant = t;
newevent.type = 'send_mac';
newevent.net.type = 'rrep';
newevent.net.src = j;
newevent.net.dst = i;
newevent.pkt.tx = j;
newevent.pkt.rv = newevent.net.route(length(newevent.net.route)-1); % next hop
newevent.pkt.type='data';
newevent.pkt.size=size_rrep;
newevent.pkt.rate=default_rate;
newevent.pkt.ttl = default_ttl; % unicast question: what value for this TTL?
newevent.pkt.power=default_power;
newevent.pkt.id=0; % will be updated in 'send_phy'
newevent.pkt.nav=0; % will be updated in lower layer
NewEvents = [NewEvents; newevent]; clear newevent;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -