⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 action.m

📁 一个无线网络仿真程序
💻 M
📖 第 1 页 / 共 4 页
字号:
                % 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 + -