參考文獻
[1] 802.11 Wireless Networks: The Definitive Guide, Mattbew S. Gast
[2] Overhaul of IEEE 802.11 Modeling and Simulation in NS-2, Qi Chen, Felix Schmidt-Eisenlohr.
[3] C++ Source codes of NS-2
[4] IEEE Std-2007
[5] 無線局域網(WLAN)——原理,技術與應用,劉乃安
[6] supplement-IEEE Std 802.11b-1999
The CS/CCA procedure is executed while the receiver is turned on and the STA is not currently receiving or transmitting a packet. The CS/CCA procedure is used for two purposes: to detect the start of a network signal that can be received (CS) and to determine whether the channel is clear prior to transmitting a packet (CCA).噹噹前工作站不處於正在接收或者發送數據包並且接收機打開時,CS/CCA過程會被執行。CS/CCA過程的啓動有兩個目的:探測網絡信號是否可以被開始接收以及當前信道是否空閒從而可以發送數據包。
在IEEE Std 802.11-2007中提到,“ The method of determining CS/CCA is unspecified”,也就是說CS/CCA的方式並沒有指定,僅僅給出了它應該實現那些功能。所以下面所給出五種CS/CCA的實現方式是在某些協議(supplement-IEEE Std 802.11b-1999,802.11 Wireless Networks: The Definitive Guide, Mattbew S. Gast)的補充文件裏定義的。
一共有五種CS/CCA實現方式,在直接序列物理層中(DSSS PHY):
Mode1,當能量超過能量檢測(energy detection, ED)閥值時。它會彙報媒介處於忙碌狀態,ED閥值因功率而異。
Mode2,採用這種模式的實現產品必須搜尋真正的DSSS信號,如果檢測到,計算信號能量低於檢測閥值ED,也會彙報該信道處於忙碌狀態。
Mode3,結合了Mode1和Mode2,所檢測到的信號必須具備足夠的能量,纔會向上一層彙報信道處於忙碌狀態。
Mode4,實現時Mode4是用來尋找真是信號。一旦被觸發,實現Mode4 CCA的產品會開啓一個月3.65ms的定時器,如果在定時器結束時還沒有發現有效的HR/DSSS信號,媒介就被視爲處於閒置狀態。3.65ms相當於5.5Mps傳送最大可能幀所需時間。
Mode5,結合了Mode4和Mode1,所檢測到的信號還必須有相當能量,才能向上層彙報信道處於忙碌狀態。
這裏注意到,Mode1,Mode2,Mode3用於DSSS PHY,而Mode1,Mode4,Mode5用於HR/DSSS PHY。而在FH PHY,OFDM PHY相關文獻中並沒有指定,兼容了1和2Mps的DSSS調製(802.11)和5.5與11Mps的CCK調製(802.11b)以及6,12與24Mps的OFDM調製的802.11g只定義了一種CCA模式:除了檢測能量的最低閥值,也用瞭解讀信號。在傳輸時隙開始時,若接收到的功率高於-76dBm的信號,則視爲有效信號。CCA與PLCP級的虛擬載波監聽(virtual carrier sense)機制整合在一起。接收到PLCP標頭時,其後會包括length字段,顯示媒介將忙碌多長時間。這段時間內,物理層將持續彙報媒介處於忙碌狀態。
物理層數據的接收
物理層包括兩個部分:物理層匯聚過程(Physical Layer Convergence Procedure)子層:直接與MAC接觸。起到承上啓下的功能。
物理媒體依賴(Phsical Medium Dependent)子層:直接與無線信道接觸。將數據通過天線傳輸以及接收。當然上述的CCA功能顯然位於物理層中。
每一次數據的發送都會選擇一個特定的調製方式和編碼速率,對於一個接收機來說,它必須知道探測到的信號到底是信號還是噪聲,這個數據幀到底持續多長這些信息,它才能夠成功的接收一個數據幀。
物理層的幀通常會以一個訓練序列也作爲PLCP前導(Preamble),這個前導碼會告知接收機幀的到來。這個前導碼之後是PLCP幀頭,這個幀頭包含調製方式,編碼速率,幀長度等等關於數據幀的信息,通常情況下,一個工作站是無法同時進行收發功能的,所以一個工作站只會處於一下三個狀態之一:監聽信道,發送從MAC層傳來的數據幀,或者接收一個數據幀。
當站點監測信道時,它通過使用特定的檢波(解調)方式檢出已知模式前導碼,如果監測出來,接收機就試圖對PLCP頭進行解碼,如果成功解碼將隨後對PLCP頭裏duration時間內所到來的射頻波進行解調,在這個過程結束之前,接收機將把所有到來的信號看作是屬於當前的數據幀,並對他們進行解調。最後將所解調出來的bits傳送到MAC層進行CRC校驗看數據幀是否已經成功接收。
網絡仿真軟件對物理層的仿真能力比較弱,下面是我通過閱讀ns2的相關源代碼所總結的關於802.11 物理層在ns2中是如何實現的。
聽說在ns2.23之前是ns2對802.11的物理層的支持比較弱。從2.33開始,NS2正式添加了幾個新的802.11模塊,其中一個便是由Mercedes-Benz研發部門和Karlsruhe大學聯合開發的802.11Ext模塊。該模塊的主要特點包括:模塊化的設計、累計SINR計算、MAC幀捕獲能力、支持多種調製機制、物理層跟蹤和Nakagami衰減模型等。主要包括ns/mac/mac-802_11Ext.[h, cc]、ns/mac/wireless-phyExt.[h,cc]、ns/mobile/nakagami.[h, cc]和ns/apps/pbc.[h, cc]等。
#ifndef ns_WirelessPhyExt_h
#define ns_WirelessPhyExt_h
#include "phy.h"
#include "propagation.h"
#include "modulation.h"
#include "omni-antenna.h"
#include "mobilenode.h"
#include "timer-handler.h"
#include
#include
enum PhyState {SEARCHING = 0, PreRXing = 1, RXing = 2, TXing = 3};
typedef struct ModulationParam {
int schemeIndex;
char schemeName[10];
double SINR_dB;
double SINR_ratio;
int NDBPS; //Data Bits Per Symbol
} ModulationParam;
const struct ModulationParam modulation_table[4] = {
// mod name SINRdB SINR NDBPS bit
{ 0, "BPSK", 5, 3.1623, 24 }, { 1, "QPSK", 8, 6.3096, 48 }, { 2,
"QAM16", 15, 31.6228, 96 }, { 3, "QAM64", 25, 316.2278, 192 } };
讓我們慢慢的來閱讀這段代碼。
首先是對物理層狀態的定義:
enum PhyState {SEARCHING = 0, PreRXing = 1, RXing = 2, TXing = 3};分爲搜索,預接收,接收和發送四種狀態。
然後是對調製參數的定義:
const struct ModulationParam modulation_table[4] = {
{ 0, "BPSK", 5, 3.1623, 24 },
{ 1, "QPSK", 8, 6.3096, 48 },
{ 2, "QAM16", 15, 31.6228, 96 },
{ 3, "QAM64", 25,316.2278,192 } };
總共這裏提供了四種調製方式及其參數。
當物理層處於搜索狀態時,物理層檢測每一個無線信到上傳輸的數據幀,如果該數據幀達到一定的信號能量,比如SINR>BPSK threshold,也就說達到了某種調製方式的門限,那麼物理層就進入預接收狀態。
當物理層處於預接收狀態時,實際上這段時間是接收前導碼和PLCP頭,如果在整個這段時間內,信號的SINR值 都滿足門限要求,那麼就物理層就進接收狀態。如果在這段時間內從信道到來的信號有足夠的能量破壞對當前的接收,那麼物理層就裝入到搜索狀態,但是如果後來 的幀有足夠的信號強度讓物理層更能監聽到自己的前導碼,那麼物理層就會繼續處於預接收狀態並且重置計數器開始新的數據幀的接收。
當物理層處於接收狀態時,物理層接收的是數據幀,物理層會時刻檢測到達幀的SINR在整個duration時間內,如果有某個時刻SINR小於調製解調或者編碼的要求門限,那麼物理層就會在這個地方標記錯誤。等待接收計數器結束。數據幀就會傳遞給MAC層,而錯誤標記的地方直接有CRC校驗決定。
上述是在body capture 功能沒有打開的時候,這個body capture的開啓與否表明的是物理層在接收數據幀的時候能否被後續的幀所打擾從而觸發物理層回到預接收狀態進行新的前導碼和PLCP頭的接收。
當物理層收到MAC層的發送命令時,物理層就會轉到發送狀態,無論此時物理層處於什麼狀態。當物理層處於發送狀態時,從信道中到來的幀都會被丟棄,只是被能力檢測模塊當作干擾。根據載波監聽機制,通常情況下MAC層不會在預接收和接收狀態非物理層發出傳送命令。MAC層永遠不會在物理層處於發送狀態的時候發出發送命令。
具體的代碼實現如下(節選自ns2.34wireless-phyExt.cc):
int WirelessPhyExt::sendUp(Packet *p) {
。。。。。。
。。。。。。
switch (state) {
case TXing:
//物理層正處於發送狀態,不能執行接收功能。直接丟棄。
pkt_recvd = discard(p, Pr, "TXB");
setState(TXing);
break;
case SEARCHING:
//物理層處於搜索狀態。先通過能力檢測模塊檢測SNR是否達到相關門限,如果達到,那
//麼接收前導碼,重置物理層狀態。開啓計時器。
if ((powerMonitor->SINR(Pr)
>= modulation_table[BasicModulationScheme_].SINR_ratio)) {
power_RX = Pr;
pkt_RX=p->copy();
setState(PreRXing);
preRX_Timer.sched(HeaderDuration_); // preamble and PCLP header
break;
} else {
//能量達不到,丟棄該幀
//pkt_recvd =discard(p,Pr,"");
pkt_recvd =discard(p, Pr, "SXB");
setState(SEARCHING);
break;
}
case PreRXing:
//如果物理層處於預接收狀態,能量檢測模塊檢測當前接收的幀的SINR是否能夠破壞當//前接收,如果不是,忽略帶來
if (powerMonitor->SINR(power_RX)
>= modulation_table[BasicModulationScheme_].SINR_ratio) {
//case 4
pkt_recvd = discard(p, Pr, "PXB");
if (PHY_DBG)
log("PCAP 1st SUCC", "");
setState(PreRXing);
break;
} else {
// 否則就重置計時器,開始新幀的接收。
// case 2
pkt_recvd = discard(pkt_RX, power_RX, "PXB");
Packet::free(pkt_RX);
power_RX=0;
preRX_Timer.cancel();
pkt_RX=0;
if (PHY_DBG)
log("PCAP 1st FAIL", "");
if (PreambleCaptureSwitch_) {
//此處描述是否開啓了Preamble Capture
if (powerMonitor->SINR(Pr) >= SINR_PreambleCapture_) {
pkt_RX=p->copy();
power_RX =Pr;
if (PHY_DBG)
log("PCAP 2nd SUCC", "");
setState(PreRXing);
preRX_Timer.sched(HeaderDuration_);
break;
} else {
//case 3
pkt_recvd = discard(p, Pr, "PXB");
if (PHY_DBG)
log("PCAP 2nd FAIL", "");
setState(SEARCHING);
break;
}
} else {
pkt_recvd = discard(p, Pr, "PXB");
if (PHY_DBG)
log("PCAP 2nd FAIL N/A", "");
setState(SEARCHING);
break;
}
}
case Rxing:
//同PreRxing
if (powerMonitor->SINR(power_RX) >= SINR_Th_RX) {
//case 8
pkt_recvd = discard(p, Pr, "RXB");
if (PHY_DBG)
log("DCAP 1st SUCC", "");
setState(RXing);
break;
} else {
if (PHY_DBG)
log("DCAP 1st FAIL", "");
HDR_CMN(pkt_RX)->error()=1;
if (DataCaptureSwitch_) {
if (powerMonitor->SINR(Pr) >= SINR_DataCapture_) {
// case 9
rX_Timer.cancel();
discard(pkt_RX, power_RX, "RXB");
pkt_RX=0;
//------ start the prerx of this new packet p---//
pkt_RX=p->copy();
power_RX =Pr;
if (PHY_DBG)
log("DCAP 2nd SUCC", "");
setState(PreRXing);
preRX_Timer.sched(HeaderDuration_);
} else {
// case 10
pkt_recvd = discard(p, Pr, "RXB");
if (PHY_DBG)
log("DCAP 2nd FAIL", "");
setState(RXing);
}
} else {
// case 11
pkt_recvd = discard(p, Pr, "RXB");
if (PHY_DBG)
log("DCAP 2nd FAIL N/A", "");
setState(RXing);
}
break;
}
default:
cout<<"packet arrive from chanel at invalid PHY state"<<endl; <="" font="" style="word-wrap: break-word;">
exit(-1);
}
}
return 0; // the incoming MAC frame will be freed by phy.cc.
}
需要注意的是,在所有ns2的仿真代碼裏,up和down直接代表這個函數是接收還是發送,比如針對物理層的函數來說,如果是up的話,那麼說明數據幀從信道來,也就是接收。如果是down的話,那麼說明數據幀從MAC層來,也就發送。
能量檢測模塊
現面我們來看看過於上面所提到的能量檢測模塊。
enum PowerMonitorState {IDLE = 0, BUSY = 1};
struct interf {
double Pt;
double end;
};
class PowerMonitor : public TimerHandler {
public:
PowerMonitor(WirelessPhyExt *);
void recordPowerLevel(double power, double duration);
double getPowerLevel();
void setPowerLevel(double);
double SINR(double Pr);
void expire(Event *); //virtual function, which must be implemented
private:
double CS_Thresh;
double monitor_Thresh;//packet with power > monitor_thresh will be recorded in the monitor
double powerLevel;
WirelessPhyExt * wirelessPhyExt;
list interfList_;
};
能量檢測模塊對應的是物理層的物理媒體相關(Physical Media Dependent, PMD)子層。PMD是唯一直接與信道中的模擬射頻信號相交互的子層。所以接收信號的所有信息都會在這個模塊進行處理。能量檢測模塊跟蹤節點所有的噪聲和干擾,無論什麼時候,如果積累的噪聲和干擾達到載波監聽的門限,它就會讓MAC層改變載波監聽狀態。應該注意到的是,節點自己的傳輸也會使節點的載波監聽狀態是處於忙碌的。
下面我們來仔細解讀它的代碼實現(節選自ns2.34的wireless-phyExt.cc):
PowerMonitor::PowerMonitor(WirelessPhyExt * phy) {
wirelessPhyExt = phy;
CS_Thresh = wirelessPhyExt->CSThresh_; // monitor_Thresh = CS_Thresh;
monitor_Thresh = wirelessPhyExt->PowerMonitorThresh_;
powerLevel = wirelessPhyExt->noise_floor_; // noise floor is -99dbm
}
這個是構造函數,完成初始化。
void PowerMonitor::recordPowerLevel(double signalPower, double duration) {
// to reduce the number of entries recorded in the interfList
if (signalPower < monitor_Thresh )
return;
interf timerEntry;
timerEntry.Pt = signalPower;
timerEntry.end = Scheduler::instance().clock() + duration;
list:: iterator i;
for (i=interfList_.begin(); i != interfList_.end() && i->end <= timerEntry.end; i++) { }
interfList_.insert(i, timerEntry);
resched((interfList_.begin())->end - Scheduler::instance().clock());
powerLevel += signalPower; // update the powerLevel
if (wirelessPhyExt->getState() == SEARCHING && powerLevel >= CS_Thresh) {
wirelessPhyExt->sendCSBusyIndication();
}
}
double PowerMonitor::getPowerLevel() {
if (powerLevel > wirelessPhyExt->noise_floor_)
return powerLevel;
else
return wirelessPhyExt->noise_floor_;
}
void PowerMonitor::setPowerLevel(double power) {
powerLevel = power;
}
double PowerMonitor::SINR(double Pr) {
if (getPowerLevel()-Pr<=0) {
//cout<<"PowerLevel lower than Pr"<<endl;exit(-1); <="" font="" style="word-wrap: break-word;">
//char msg[1000];
//sprintf(msg,"PowerLevel %f lower than Pr %f = %f",getPowerLevel()*1e9,Pr*1e9,(getPowerLevel()-Pr));
//wirelessPhyExt->log("PMX",msg);
//exit(-1);
return 0.0; //internal event contention, new msg arrives betweeen the expire of two timers.
}
return Pr/(getPowerLevel()-Pr);
}
void PowerMonitor::expire(Event *) {
double pre_power = powerLevel;
double time = Scheduler::instance().clock();
list:: iterator i;
i=interfList_.begin();
while(i != interfList_.end() && i->end <= time) {
powerLevel -= i->Pt;
interfList_.erase(i++);
}
if (!interfList_.empty())
resched((interfList_.begin())->end - Scheduler::instance().clock());
char msg[1000];
sprintf(msg, "Power: %f -> %f", pre_power*1e9, powerLevel*1e9);
wirelessPhyExt->log("PMX", msg);
// check if the channel becomes idle ( busy -> idle )
if (wirelessPhyExt->getState() == SEARCHING && powerLevel < CS_Thresh) {
wirelessPhyExt->sendCSIdleIndication();
}
}
上述成員函數完成信道的掃描並且向MAC層指示。