标题:代码各种不懂,求各位大虾指点
只看楼主
yi笑倾城
Rank: 1
等 级:新手上路
帖 子:1
专家分:0
注 册:2011-5-5
 问题点数:0 回复次数:0 
代码各种不懂,求各位大虾指点
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;
              
搜索更多相关主题的帖子: function 
2011-05-05 13:30



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-338874-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 1.096906 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved