NS3 WiFiMode说明
WiFiMode官方文档介绍
代表单一传输模式
WifiMode由单个整数实现,用于在全局数组中查找相关传输模式的特性。
因此,保持WifiMode变量是非常便宜的。
源码分析
在/src/wifi/model/wifi-phy.cc中定义了OFDM DSSS HTMCS等一系列模式。
WifiMode
WifiPhy::GetOfdmRate6Mbps ()
{
static WifiMode mode =
WifiModeFactory::CreateWifiMode ("OfdmRate6Mbps",
WIFI_MOD_CLASS_OFDM,
true,
WIFI_CODE_RATE_1_2,
2);
return mode;
}
WifiMode
WifiPhy::GetOfdmRate9Mbps ()
{
static WifiMode mode =
WifiModeFactory::CreateWifiMode ("OfdmRate9Mbps",
WIFI_MOD_CLASS_OFDM,
false,
WIFI_CODE_RATE_3_4,
2);
return mode;
}
在这里就这几行代码稍稍分析一下。
WifiModeFactory的构造器函数如下:
WifiModeFactory::WifiModeFactory ()
{
}
但是这个构造函数是私有的,外界无法访问。
WifiModeFactory 对象的创建,可以通过下面的GetFactory方法:
WifiModeFactory *
WifiModeFactory::GetFactory (void)
{
static bool isFirstTime = true;
static WifiModeFactory factory;
if (isFirstTime)
{
uint32_t uid = factory.AllocateUid ("Invalid-WifiMode");
WifiModeItem *item = factory.Get (uid);
item->uniqueUid = "Invalid-WifiMode";
item->modClass = WIFI_MOD_CLASS_UNKNOWN;
item->constellationSize = 0;
item->codingRate = WIFI_CODE_RATE_UNDEFINED;
item->isMandatory = false;
item->mcsValue = 0;
isFirstTime = false;
}
return &factory;
}
可以发现,上面的静态方法中factory静态变量,仅被初始化一次,全局访问这一个静态变量。
WifiModeItem 是结构体。
struct WifiModeItem
{
std::string uniqueUid;
enum WifiModulationClass modClass;
uint16_t constellationSize;
enum WifiCodeRate codingRate;
bool isMandatory;
uint8_t mcsValue;
};
有了上面的准备工作,重点看下面的CreateWifiMode 方法:
WifiMode
WifiModeFactory::CreateWifiMode (std::string uniqueName,
enum WifiModulationClass modClass,
bool isMandatory,
enum WifiCodeRate codingRate,
uint16_t constellationSize)
{
WifiModeFactory *factory = GetFactory ();
uint32_t uid = factory->AllocateUid (uniqueName);
WifiModeItem *item = factory->Get (uid);
item->uniqueUid = uniqueName;
item->modClass = modClass;
//The modulation class for this WifiMode must be valid.
NS_ASSERT (modClass != WIFI_MOD_CLASS_UNKNOWN);
item->codingRate = codingRate;
if ((codingRate == WIFI_CODE_RATE_UNDEFINED) &&
modClass != WIFI_MOD_CLASS_DSSS &&
modClass != WIFI_MOD_CLASS_HR_DSSS)
{
NS_FATAL_ERROR ("Error in creation of WifiMode named " << uniqueName << std::endl
<< "Code rate must be WIFI_CODE_RATE_UNDEFINED iff
Modulation Class is WIFI_MOD_CLASS_DSSS or
WIFI_MOD_CLASS_HR_DSSS");
}
item->constellationSize = constellationSize;
item->isMandatory = isMandatory;
NS_ASSERT (modClass != WIFI_MOD_CLASS_HT && modClass != WIFI_MOD_CLASS_VHT);
//fill unused mcs item with a dummy value
item->mcsValue = 0;
return WifiMode (uid);
}
CreateWifiMode 方法首先通过GetFactory 方法创建一个WifiModeFactory 对象,利用AllocateUid 方法产生一个唯一的uid,通过唯一的uid产生一个WifiModeItem 结构体,结构体对象中保存了WiFimode中的参数。
由于uid唯一的,WiFiMode对象只需要保存uid的值,就可以通过uid值传递给WifiModeFactory 对象,得到WifiModeItem 结构体,而该结构体保存了WiFimode中的参数。
上面的CreateWifiMode 方法中使用到的AllocateUid 方法和Get 方法如下:
uint32_t
WifiModeFactory::AllocateUid (std::string uniqueUid)
{
uint32_t j = 0;
for (WifiModeItemList::const_iterator i = m_itemList.begin ();
i != m_itemList.end (); i++)
{
if (i->uniqueUid == uniqueUid)
{
return j;
}
j++;
}
uint32_t uid = m_itemList.size ();
m_itemList.push_back (WifiModeItem ());
return uid;
}
struct WifiModeFactory::WifiModeItem *
WifiModeFactory::Get (uint32_t uid)
{
NS_ASSERT (uid < m_itemList.size ());
return &m_itemList[uid];
}
其中的m_itemList对象就是一个列表,保存了每一个结构体对象,结构体对象保存了WiFimode的相应的参数。
AllocateUid 方法设计的非常巧妙,返回的uid的值就是对应的结构器在m_itemList中的位置。所以可通过将uid传递给Get方法,从m_itemList列表中获取到对应的结构体对象。
WifiMode::WifiMode (uint32_t uid)
: m_uid (uid)
{
}
WifiMode对象通过这个构造函数,只需要保存uid的值,就可以通过下面的代码:
struct WifiModeFactory::WifiModeItem *item = WifiModeFactory::GetFactory ()->Get (m_uid);
仅仅通过这一行代码就可以获取到WifiModeItem 结构体对象,获取到wifimode的参数。