QualNet收发包过程分析(三)

接上文https://blog.csdn.net/zhang1806618/article/details/107753611

MacDot11StationTransmitFrame()函数区分链路当前状态,或调用MacDot11StationTransmitDataFrame()发送数据帧,或调用MacDot11StationTransmitRTSFrame()发送RTS帧。以发送数据帧为例,由目的地址判断是广播还是单播,广播将不使用RTS-CTS机制,更改链路状态后调用MacDot11StationStartTransmittingPacket发送数据。单播时区分是否使用RTS-CTS机制,设置延迟,然后调用MacDot11StationStartTransmittingPacket

static //inline//
void MacDot11StationTransmitDataFrame(
    Node* node,
    MacDataDot11* dot11)
{
    Mac802Address destAddr;
    //广播
    if (destAddr == ANY_MAC802) 
    {
        Message* dequeuedPacket;
        DOT11_FrameHdr* hdr;
        hdr = (DOT11_FrameHdr*)MESSAGE_ReturnPacket(dequeuedPacket);
        if (MacDot11IsAp(dot11) && dot11->dot11TxFrameInfo != NULL)
        {
            if (dot11->dot11TxFrameInfo->frameType == DOT11_BEACON)             
                MacDot11StationSetState(node, dot11, DOT11_X_BEACON);
            else
                MacDot11StationSetState(node, dot11, DOT11_X_BROADCAST);
        }
        else
            MacDot11StationSetState(node, dot11, DOT11_X_BROADCAST);
        MacDot11StationStartTransmittingPacket(node, dot11, dequeuedPacket,
            dot11->delayUntilSignalAirborn);
    }
    //单播/组播
    else 
    {
        clocktype transmitDelay = 0;
        DOT11_SeqNoEntry *entry;
        DOT11_FrameHdr* hdr;
        DOT11e_FrameHdr* Qhdr;
        Message* pktToPhy = MESSAGE_Duplicate(node, dot11->currentMessage);
        dot11->waitingForAckOrCtsFromAddress = destAddr;
        if (MESSAGE_ReturnPacketSize(dot11->currentMessage) > fragThreshold)
        {...}
        else 
        {
             if (hdr->frameType == DOT11_PS_POLL)                 
                MacDot11StationSetState(node, dot11, DOT11_X_PSPOLL);
             else
                MacDot11StationSetState(node, dot11, DOT11_X_UNICAST);
            //使用RTS-CTS机制
            if ((MESSAGE_ReturnPacketSize(pktToPhy)>
                dot11->rtsThreshold)&&
               (hdr->frameType != DOT11_PS_POLL))       
                transmitDelay += dot11->sifs;
            //不使用RTS-CTS机制
            else             
                transmitDelay += dot11->delayUntilSignalAirborn;
            MacDot11StationStartTransmittingPacket(node, dot11, pktToPhy, transmitDelay);
        }
    }
}

MacDot11StationStartTransmittingPacket主要作用是获取帧的信息,判断是控制帧/数据帧,广播帧/单播帧,本地帧/非本地帧,然后调用物理层函数发送帧。 

static //inline//
void MacDot11StationStartTransmittingPacket(
    Node* node,
    MacDataDot11* dot11,
    Message* packet,
    clocktype delay)
{
    //接口未启用
    if (!MAC_InterfaceIsEnabled(node, dot11->myMacData->interfaceIndex))
    {        
        MESSAGE_Free(node, packet);        
        return;
    }
    //获取数据帧信息,判断是控制帧/数据帧,广播帧/单播帧,本地帧/非本地帧 
    BOOL isCtrlFrame = FALSE;
    BOOL isMyFrame = FALSE;
    BOOL isAnyFrame = FALSE;
    int headerSize = -1;
    Mac802Address destAddr;
    NodeId destID;
    MacDot11GetPacketProperty(
        node,
        packet,
        dot11->myMacData->interfaceIndex,
        headerSize,
        destAddr,
        destID,
        isCtrlFrame,
        isMyFrame,    
        isAnyFrame);
    //更新统计信息
    MacDot11UpdateStatsSend(
        node,
        packet,
        dot11->myMacData->interfaceIndex,
        isAnyFrame,
        isMyFrame,
        !isCtrlFrame,
        destAddr);
    //调用物理层发送数据帧
    PHY_StartTransmittingSignal(
        node, dot11->myMacData->phyNumber, packet, TRUE, delay);
}

1.5 物理层

phy.cpp中函数PHY_StartTransmittingSignal(),区分物理层协议分别调用相应协议函数。以802.11为例,phy_802_11.cpp中函数Phy802_11StartTransmittingSignal()直接调用StartTransmittingSignal,添加首部并调用函数ReleaseSignalToChannel()将信号发送至传输信道。

static
void StartTransmittingSignal(
    Node* node,
    int phyIndex,
    Message* packet,
    BOOL useMacLayerSpecifiedDelay,
    clocktype initDelayUntilAirborne,
    BOOL sendDirectionally,
    double azimuthAngle)
{
    //获取传输信道
    PHY_GetTransmissionChannel(node, phyIndex, &channelIndex);
    assert(phy802_11->mode != PHY_TRANSMITTING);    
    //物理层正在接收信号
    if (phy802_11->mode == PHY_RECEIVING) 
    {
        //丢弃包
         PHY_NotificationOfPacketDrop(
             node,
             phyIndex,
             channelIndex,
             phy802_11->rxMsg,
             "PHY Stop Rx for Tx",
             phy802_11->rxMsgPower_mW,
             phy802_11->interferencePower_mW,
             0.0);        
        Phy802_11UnlockSignal(phy802_11);
    }
    Phy802_11ChangeState(node, phyIndex, PHY_TRANSMITTING);

    //添加物理层首部
    Phy802_11AddPlcpHeader(node, phy802_11, packet);

    if (PHY_IsListeningToChannel(node, phyIndex, channelIndex))
    {
        PHY_StopListeningToChannel(node, phyIndex, channelIndex);
    }
    //根据传输模型,发送信号至传播信道
    if (thisPhy->antennaData->antennaModelType == ANTENNA_PATTERNED)
    {
        //全向天线
        if (!sendDirectionally) {
            ReleaseSignalToChannel(
                node,
                packet,
                phyIndex,
                channelIndex,
                phy802_11->txPower_dBm,
                duration,
                delayUntilAirborne,
                0.0);
        }
        //定向天线
        else {
            ReleaseSignalToChannel(
                node,
                packet,
                phyIndex,
                channelIndex,
                phy802_11->txPower_dBm,
                duration,
                delayUntilAirborne,
                phy802_11->directionalAntennaGain_dB);
        }
    }
    else
    {...}
    //调度结束发送事件
    endMsg = MESSAGE_Alloc(node,
                            PHY_LAYER,
                            0,
                            MSG_PHY_TransmissionEnd);
    MESSAGE_SetInstanceId(endMsg, (short) phyIndex);
    MESSAGE_Send(node, endMsg, delayUntilAirborne + duration + 1);
    phy802_11->txEndTimer = endMsg;   
}

ReleaseSignalToChannel()调用函数PROP_ReleaseSignal()将信号发送至信道。

1.6 传播媒介

propagation.h中申明了函数PROP_ReleaseSignal(),但未找到该函数的实现,可能属于内核代码,无法阅读。

至此,信号已经传递至信道,带传递信号结束定时器消息endMsg执行时,结束信号传递,一个包传递结束。

猜你喜欢

转载自blog.csdn.net/zhang1806618/article/details/107781895