接上文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执行时,结束信号传递,一个包传递结束。