38 #include <libxml/parser.h> 46 const int PRECISION_FACTOR{100};
48 inline xmlChar * toXMLChar(
const char * p)
50 return reinterpret_cast<xmlChar *
>(
const_cast<char *
>(p));
57 pPlatformService_{pPlatformService},
68 EMANE::Models::IEEE80211ABG::PCRManager::openDoc(
const std::string & uri,
69 xmlParserCtxtPtr * ppContext,
70 xmlDoc ** ppDocument, xmlNode ** ppRoot)
72 if((*ppContext = xmlNewParserCtxt()) == NULL)
74 std::stringstream excString;
75 excString <<
"IEEE80211ABG::PCRManager::openDoc: Failed to allocate parser context" << std::ends;
80 else if((*ppDocument = xmlCtxtReadFile(*ppContext, uri.c_str(), NULL, XML_PARSE_DTDVALID)) == NULL)
82 std::stringstream excString;
83 excString <<
"IEEE80211ABG::PCRManager::openDoc: Failed to parse document " << uri << std::ends;
88 else if((*ppContext)->valid ==
false)
90 std::stringstream excString;
91 excString <<
"IEEE80211ABG::PCRManager::openDoc: Document in " << uri <<
" is not valid" << std::ends;
96 else if((*ppRoot = xmlDocGetRootElement(*ppDocument)) == NULL)
98 std::stringstream excString;
99 excString <<
"IEEE80211ABG::PCRManager::openDoc: Could not get root element" << std::ends;
107 EMANE::Models::IEEE80211ABG::PCRManager::closeDoc(xmlParserCtxtPtr * ppContext, xmlDoc ** ppDocument)
111 xmlFreeParserCtxt(*ppContext);
117 xmlFreeDoc(*ppDocument);
131 xmlParserCtxtPtr pContext{};
135 std::stringstream excString;
136 excString <<
"IEEE80211ABG::PCRManager::load: must supply curve file name" << std::ends;
142 openDoc(uri, &pContext, &doc, &root);
145 xmlNodePtr cur {root};
153 if((!xmlStrcmp(cur->name, toXMLChar(
"pcr"))))
155 getTable(cur->xmlChildrenNode, pcrPorMap_);
162 closeDoc(&pContext, &doc);
165 for(
auto & iter : pcrPorMap_)
167 if(iter.second.pcr_.size() < 1)
169 std::stringstream excString;
170 excString <<
"IEEE80211ABG::PCRManager::load: need at least 1 point to define a pcr curve " << std::ends;
182 EMANE::Models::IEEE80211ABG::PCRManager::getTable(xmlNodePtr cur, PCRPORMap & map)
186 if((!xmlStrcmp(cur->name, toXMLChar(
"table"))))
192 getDataRate(cur->xmlChildrenNode, map);
201 EMANE::Models::IEEE80211ABG::PCRManager::getDataRate(xmlNodePtr cur, PCRPORMap & map)
205 if((!xmlStrcmp(cur->name, toXMLChar(
"datarate"))))
214 getRows(cur->xmlChildrenNode, entry.pcr_);
216 if(map.insert(std::make_pair(u16DataRateIndex, entry)).second ==
false)
218 std::stringstream excString;
219 excString <<
"IEEE80211ABG::PCRManager::getDataRate: duplicate datarate index value " << u16DataRateIndex << std::ends;
230 EMANE::Models::IEEE80211ABG::PCRManager::getRows(xmlNodePtr cur, PCREntryVector & vec)
234 if((!xmlStrcmp(cur->name, toXMLChar(
"row"))))
243 for(
const auto & iter : vec)
245 if(fSINR == iter.fSINR_)
247 std::stringstream excString;
248 excString <<
"IEEE80211ABG::PCRManager::getRows: duplicate sinr value " << fSINR << std::ends;
251 else if(fSINR < iter.fSINR_)
253 std::stringstream excString;
254 excString <<
"IEEE80211ABG::PCRManager::getRows: out of order sinr value, must be in increasing value " 255 << fSINR << std::ends;
261 vec.push_back(PCREntry(fSINR, fPOR));
270 EMANE::Models::IEEE80211ABG::PCRManager::interpolate()
273 for(
auto & iter : pcrPorMap_)
276 for(
size_t i = 0; i < (iter.second.pcr_.size() - 1); ++i)
279 const int x1{
static_cast<int>(iter.second.pcr_[i].fSINR_ * PRECISION_FACTOR)};
282 const float y1{iter.second.pcr_[i].fPOR_};
285 const int x2{
static_cast<int>(iter.second.pcr_[i + 1].fSINR_ * PRECISION_FACTOR)};
288 const float y2{iter.second.pcr_[i + 1].fPOR_};
291 const float slope{(y2 - y1) / (x2 - x1)};
294 for(
int dx = x1; dx < x2; ++dx)
297 const float por{(dx - x1) * slope + y1};
300 iter.second.por_.push_back(por);
304 iter.second.por_.push_back(iter.second.pcr_[iter.second.pcr_.size() - 1].fPOR_);
314 const auto iter = pcrPorMap_.find(u16DataRateIndex);
316 if(iter != pcrPorMap_.end())
319 if(fSINR < iter->second.pcr_.front().fSINR_)
323 "MACI %03hu PCRManager::%s: sinr %3.2f, for datarate index %hu, " 324 "is below the low limit sinr of %3.2f",
329 iter->second.pcr_.front().fSINR_);
335 else if(fSINR > iter->second.pcr_.back().fSINR_)
339 "MACI %03hu PCRManager::%s: sinr %3.2f, for datarate index %hu, " 340 "is above the high limit sinr of %3.2f",
345 iter->second.pcr_.back().fSINR_);
355 if(fSINR == iter->second.pcr_.front().fSINR_ && fSINR == iter->second.pcr_.back().fSINR_)
358 fPOR = iter->second.pcr_.front().fPOR_;
363 const int sinrScaled{
static_cast<int>(fSINR * PRECISION_FACTOR)};
366 const int sinrOffset{
static_cast<int>(iter->second.pcr_.front().fSINR_ * PRECISION_FACTOR)};
369 int idx{sinrScaled - sinrOffset};
372 if(idx >= static_cast<int>(iter->second.por_.size()))
374 idx = iter->second.por_.size() - 1;
378 fPOR = iter->second.por_[idx];
382 "MACI %03hu PCRManager::%s: lookup por %3.2f at table index %d",
390 if(tablePacketSize_ > 0)
392 fPOR = powf(fPOR, static_cast<float>(packetLen) / tablePacketSize_);
397 "MACI %03hu PCRManager::%s: sinr %3.2f, for datarate index %hu, por %3.2f",
412 "MACI %03hu PCRManager::%s: unsupported datarate index %hu, por %3.2f",
426 std::string EMANE::Models::IEEE80211ABG::PCRManager::getAttribute(xmlNodePtr cur,
const xmlChar *
id)
428 std::string str{
"0"};
432 xmlChar * attr {xmlGetProp(cur,
id)};
436 str =
reinterpret_cast<const char *
>(attr);
447 std::string EMANE::Models::IEEE80211ABG::PCRManager::getContent(xmlNodePtr cur)
449 std::string str{
"0"};
451 xmlChar * attr{xmlNodeGetContent(cur)};
455 str =
reinterpret_cast<const char *
>(attr);
#define LOGGER_VERBOSE_LOGGING(logger, level, fmt, args...)
ConfigurationException is thrown when an exception occurs during configuration processing.
std::uint16_t toUINT16(std::uint16_t u16Min=std::numeric_limits< std::uint16_t >::min(), std::uint16_t u16Max=std::numeric_limits< std::uint16_t >::max()) const
float toFloat(float fMin=std::numeric_limits< float >::lowest(), float fMax=std::numeric_limits< float >::max()) const
std::uint32_t toUINT32(std::uint32_t u32Min=std::numeric_limits< std::uint32_t >::min(), std::uint32_t u32Max=std::numeric_limits< std::uint32_t >::max()) const
void load(const std::string &uri)
PCRManager(NEMId id, PlatformServiceProvider *pPlatformService)
float getPCR(float fSinr, size_t size, std::uint16_t DataRateIndex)
Parameter conversion class with range checks.