OLD | NEW |
(Empty) | |
| 1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ |
| 2 /* |
| 3 * Copyright (c) 2008,2009 IITP RAS |
| 4 * |
| 5 * This program is free software; you can redistribute it and/or modify |
| 6 * it under the terms of the GNU General Public License version 2 as |
| 7 * published by the Free Software Foundation; |
| 8 * |
| 9 * This program is distributed in the hope that it will be useful, |
| 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 12 * GNU General Public License for more details. |
| 13 * |
| 14 * You should have received a copy of the GNU General Public License |
| 15 * along with this program; if not, write to the Free Software |
| 16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 17 * |
| 18 * Author: Kirill Andreev <andreev@iitp.ru> |
| 19 */ |
| 20 |
| 21 #include "ns3/mesh-wifi-interface-mac.h" |
| 22 #include "ns3/packet.h" |
| 23 #include "ns3/simulator.h" |
| 24 #include "ns3/nstime.h" |
| 25 #include "ns3/log.h" |
| 26 #include "dot11s-mac-header.h" |
| 27 #include "hwmp-protocol-mac.h" |
| 28 #include "hwmp-tag.h" |
| 29 #include "ie-dot11s-preq.h" |
| 30 #include "ie-dot11s-prep.h" |
| 31 #include "ie-dot11s-rann.h" |
| 32 #include "ie-dot11s-perr.h" |
| 33 |
| 34 namespace ns3 { |
| 35 namespace dot11s { |
| 36 |
| 37 NS_LOG_COMPONENT_DEFINE ("HwmpProtocolMac"); |
| 38 HwmpProtocolMac::HwmpProtocolMac (uint32_t ifIndex, Ptr<HwmpProtocol> protocol)
: |
| 39 m_ifIndex (ifIndex), m_protocol (protocol) |
| 40 { |
| 41 } |
| 42 HwmpProtocolMac::~HwmpProtocolMac () |
| 43 { |
| 44 } |
| 45 void |
| 46 HwmpProtocolMac::SetParent (Ptr<MeshWifiInterfaceMac> parent) |
| 47 { |
| 48 m_parent = parent; |
| 49 } |
| 50 |
| 51 bool |
| 52 HwmpProtocolMac::ReceiveData (Ptr<Packet> packet, const WifiMacHeader & header) |
| 53 { |
| 54 NS_ASSERT (header.IsData ()); |
| 55 |
| 56 MeshHeader meshHdr; |
| 57 HwmpTag tag; |
| 58 if (packet->PeekPacketTag (tag)) |
| 59 { |
| 60 NS_FATAL_ERROR ("HWMP tag is not supposed to be received by network"); |
| 61 } |
| 62 |
| 63 packet->RemoveHeader (meshHdr); |
| 64 m_stats.rxData++; |
| 65 m_stats.rxDataBytes += packet->GetSize (); |
| 66 |
| 67 //TODO: address extension |
| 68 Mac48Address destination; |
| 69 Mac48Address source; |
| 70 switch (meshHdr.GetAddressExt ()) |
| 71 { |
| 72 case 0: |
| 73 source = header.GetAddr4 (); |
| 74 destination = header.GetAddr3 (); |
| 75 break; |
| 76 default: |
| 77 NS_FATAL_ERROR ( |
| 78 "6-address scheme is not yet supported and 4-address extension is not su
pposed to be used for data frames."); |
| 79 } |
| 80 tag.SetSeqno (meshHdr.GetMeshSeqno ()); |
| 81 tag.SetTtl (meshHdr.GetMeshTtl ()); |
| 82 packet->AddPacketTag (tag); |
| 83 |
| 84 if ((destination == Mac48Address::GetBroadcast ()) && (m_protocol->DropDataFra
me (meshHdr.GetMeshSeqno (), |
| 85 source))) |
| 86 { |
| 87 return false; |
| 88 } |
| 89 return true; |
| 90 } |
| 91 |
| 92 bool |
| 93 HwmpProtocolMac::ReceiveAction (Ptr<Packet> packet, const WifiMacHeader & header
) |
| 94 { |
| 95 m_stats.rxMgt++; |
| 96 m_stats.rxMgtBytes += packet->GetSize (); |
| 97 WifiMeshActionHeader actionHdr; |
| 98 packet->RemoveHeader (actionHdr); |
| 99 WifiMeshActionHeader::ActionValue actionValue = actionHdr.GetAction (); |
| 100 if (actionHdr.GetCategory () != WifiMeshActionHeader::MESH_PATH_SELECTION) |
| 101 { |
| 102 return true; |
| 103 } |
| 104 WifiInformationElementVector elements; |
| 105 packet->RemoveHeader (elements); |
| 106 std::vector<HwmpProtocol::FailedDestination> failedDestinations; |
| 107 for (WifiInformationElementVector::Iterator i = elements.Begin(); i != element
s.End(); i ++) |
| 108 { |
| 109 if ((*i)->ElementId () == IE11S_RANN) |
| 110 { |
| 111 NS_LOG_WARN ("RANN is not supported!"); |
| 112 } |
| 113 if ((*i)->ElementId () == IE11S_PREQ) |
| 114 { |
| 115 Ptr<IePreq> preq = DynamicCast<IePreq> (*i); |
| 116 NS_ASSERT (preq != 0); |
| 117 m_stats.rxPreq++; |
| 118 if (preq->GetOriginatorAddress () == m_protocol->GetAddress ()) |
| 119 { |
| 120 continue; |
| 121 } |
| 122 if (preq->GetTtl () == 0) |
| 123 { |
| 124 continue; |
| 125 } |
| 126 preq->DecrementTtl (); |
| 127 m_protocol->ReceivePreq (*preq, header.GetAddr2 (), m_ifIndex, header.
GetAddr3 (), |
| 128 m_parent->GetLinkMetric (header.GetAddr2 ())); |
| 129 } |
| 130 if ((*i)->ElementId () == IE11S_PREP) |
| 131 { |
| 132 Ptr<IePrep> prep = DynamicCast<IePrep> (*i); |
| 133 NS_ASSERT (prep != 0); |
| 134 m_stats.rxPrep++; |
| 135 if (prep->GetTtl () == 0) |
| 136 { |
| 137 continue; |
| 138 } |
| 139 prep->DecrementTtl (); |
| 140 m_protocol->ReceivePrep (*prep, header.GetAddr2 (), m_ifIndex, header.
GetAddr3 (), |
| 141 m_parent->GetLinkMetric (header.GetAddr2 ())); |
| 142 } |
| 143 if ((*i)->ElementId () == IE11S_PERR) |
| 144 { |
| 145 Ptr<IePerr> perr = DynamicCast<IePerr> (*i); |
| 146 NS_ASSERT (perr != 0); |
| 147 m_stats.rxPerr++; |
| 148 std::vector<HwmpProtocol::FailedDestination> destinations = perr->GetA
ddressUnitVector (); |
| 149 for (std::vector<HwmpProtocol::FailedDestination>::const_iterator i =
destinations.begin (); i |
| 150 != destinations.end (); i++) |
| 151 { |
| 152 failedDestinations.push_back (*i); |
| 153 } |
| 154 } |
| 155 } |
| 156 if (failedDestinations.size () > 0) |
| 157 { |
| 158 m_protocol->ReceivePerr (failedDestinations, header.GetAddr2 (), m_ifIndex
, header.GetAddr3 ()); |
| 159 } |
| 160 NS_ASSERT (packet->GetSize () == 0); |
| 161 return false; |
| 162 } |
| 163 |
| 164 bool |
| 165 HwmpProtocolMac::Receive (Ptr<Packet> packet, const WifiMacHeader & header) |
| 166 { |
| 167 if (header.IsData ()) |
| 168 { |
| 169 return ReceiveData (packet, header); |
| 170 } |
| 171 else |
| 172 { |
| 173 if (header.IsAction ()) |
| 174 { |
| 175 return ReceiveAction (packet, header); |
| 176 } |
| 177 else |
| 178 { |
| 179 return true; // don't care |
| 180 } |
| 181 } |
| 182 } |
| 183 bool |
| 184 HwmpProtocolMac::UpdateOutcomingFrame (Ptr<Packet> packet, WifiMacHeader & heade
r, Mac48Address from, |
| 185 Mac48Address to) |
| 186 { |
| 187 if (!header.IsData ()) |
| 188 { |
| 189 return true; |
| 190 } |
| 191 HwmpTag tag; |
| 192 bool tagExists = packet->RemovePacketTag (tag); |
| 193 if (!tagExists) |
| 194 { |
| 195 NS_FATAL_ERROR ("HWMP tag must exist at this point"); |
| 196 } |
| 197 m_stats.txData++; |
| 198 m_stats.txDataBytes += packet->GetSize (); |
| 199 MeshHeader meshHdr; |
| 200 meshHdr.SetMeshSeqno (tag.GetSeqno ()); |
| 201 meshHdr.SetMeshTtl (tag.GetTtl ()); |
| 202 packet->AddHeader (meshHdr); |
| 203 header.SetAddr1 (tag.GetAddress ()); |
| 204 return true; |
| 205 } |
| 206 WifiMeshActionHeader |
| 207 HwmpProtocolMac::GetWifiMeshActionHeader () |
| 208 { |
| 209 WifiMeshActionHeader actionHdr; |
| 210 WifiMeshActionHeader::ActionValue action; |
| 211 action.pathSelection = WifiMeshActionHeader::PATH_SELECTION; |
| 212 actionHdr.SetAction (WifiMeshActionHeader::MESH_PATH_SELECTION, action); |
| 213 return actionHdr; |
| 214 } |
| 215 void |
| 216 HwmpProtocolMac::SendPreq (IePreq preq) |
| 217 { |
| 218 NS_LOG_FUNCTION_NOARGS (); |
| 219 std::vector<IePreq> preq_vector; |
| 220 preq_vector.push_back (preq); |
| 221 SendPreq (preq_vector); |
| 222 } |
| 223 void |
| 224 HwmpProtocolMac::SendPreq (std::vector<IePreq> preq) |
| 225 { |
| 226 Ptr<Packet> packet = Create<Packet> (); |
| 227 WifiInformationElementVector elements; |
| 228 for (std::vector<IePreq>::iterator i = preq.begin (); i != preq.end (); i++) |
| 229 { |
| 230 elements.AddInformationElement(Ptr<IePreq> (&(*i))); |
| 231 } |
| 232 packet->AddHeader(elements); |
| 233 packet->AddHeader (GetWifiMeshActionHeader ()); |
| 234 //create 802.11 header: |
| 235 WifiMacHeader hdr; |
| 236 hdr.SetAction (); |
| 237 hdr.SetDsNotFrom (); |
| 238 hdr.SetDsNotTo (); |
| 239 hdr.SetAddr2 (m_parent->GetAddress ()); |
| 240 hdr.SetAddr3 (m_protocol->GetAddress ()); |
| 241 //Send Management frame |
| 242 std::vector<Mac48Address> receivers = m_protocol->GetPreqReceivers (m_ifIndex)
; |
| 243 for (std::vector<Mac48Address>::const_iterator i = receivers.begin (); i != re
ceivers.end (); i++) |
| 244 { |
| 245 hdr.SetAddr1 (*i); |
| 246 m_stats.txPreq++; |
| 247 m_stats.txMgt++; |
| 248 m_stats.txMgtBytes += packet->GetSize (); |
| 249 m_parent->SendManagementFrame (packet, hdr); |
| 250 } |
| 251 } |
| 252 void |
| 253 HwmpProtocolMac::RequestDestination (Mac48Address dst, uint32_t originator_seqno
, uint32_t dst_seqno) |
| 254 { |
| 255 NS_LOG_FUNCTION_NOARGS (); |
| 256 for (std::vector<IePreq>::iterator i = m_myPreq.begin (); i != m_myPreq.end ()
; i++) |
| 257 { |
| 258 if (i->IsFull ()) |
| 259 { |
| 260 continue; |
| 261 } |
| 262 NS_ASSERT (i->GetDestCount () > 0); |
| 263 i->AddDestinationAddressElement (m_protocol->GetDoFlag (), m_protocol->Get
RfFlag (), dst, dst_seqno); |
| 264 } |
| 265 IePreq preq; |
| 266 preq.SetHopcount (0); |
| 267 preq.SetTTL (m_protocol->GetMaxTtl ()); |
| 268 preq.SetPreqID (m_protocol->GetNextPreqId ()); |
| 269 preq.SetOriginatorAddress (m_protocol->GetAddress ()); |
| 270 preq.SetOriginatorSeqNumber (originator_seqno); |
| 271 preq.SetLifetime (m_protocol->GetActivePathLifetime ()); |
| 272 preq.AddDestinationAddressElement (m_protocol->GetDoFlag (), m_protocol->GetRf
Flag (), dst, dst_seqno); |
| 273 m_myPreq.push_back (preq); |
| 274 SendMyPreq (); |
| 275 } |
| 276 void |
| 277 HwmpProtocolMac::SendMyPreq () |
| 278 { |
| 279 NS_LOG_FUNCTION_NOARGS (); |
| 280 if (m_preqTimer.IsRunning ()) |
| 281 { |
| 282 return; |
| 283 } |
| 284 if (m_myPreq.size () == 0) |
| 285 { |
| 286 return; |
| 287 } |
| 288 //reschedule sending PREQ |
| 289 NS_ASSERT (!m_preqTimer.IsRunning ()); |
| 290 m_preqTimer = Simulator::Schedule (m_protocol->GetPreqMinInterval (), &HwmpPro
tocolMac::SendMyPreq, this); |
| 291 SendPreq (m_myPreq); |
| 292 m_myPreq.clear (); |
| 293 } |
| 294 void |
| 295 HwmpProtocolMac::SendPrep (IePrep prep, Mac48Address receiver) |
| 296 { |
| 297 NS_LOG_FUNCTION_NOARGS (); |
| 298 //Create packet |
| 299 Ptr<Packet> packet = Create<Packet> (); |
| 300 WifiInformationElementVector elements; |
| 301 elements.AddInformationElement(Ptr<IePrep> (&prep)); |
| 302 packet->AddHeader (elements); |
| 303 packet->AddHeader (GetWifiMeshActionHeader ()); |
| 304 //create 802.11 header: |
| 305 WifiMacHeader hdr; |
| 306 hdr.SetAction (); |
| 307 hdr.SetDsNotFrom (); |
| 308 hdr.SetDsNotTo (); |
| 309 hdr.SetAddr1 (receiver); |
| 310 hdr.SetAddr2 (m_parent->GetAddress ()); |
| 311 hdr.SetAddr3 (m_protocol->GetAddress ()); |
| 312 //Send Management frame |
| 313 m_stats.txPrep++; |
| 314 m_stats.txMgt++; |
| 315 m_stats.txMgtBytes += packet->GetSize (); |
| 316 m_parent->SendManagementFrame (packet, hdr); |
| 317 } |
| 318 void |
| 319 HwmpProtocolMac::ForwardPerr (std::vector<HwmpProtocol::FailedDestination> faile
dDestinations, std::vector< |
| 320 Mac48Address> receivers) |
| 321 { |
| 322 NS_LOG_FUNCTION_NOARGS (); |
| 323 Ptr<Packet> packet = Create<Packet> (); |
| 324 Ptr<IePerr> perr = Create <IePerr> (); |
| 325 WifiInformationElementVector elements; |
| 326 for (std::vector<HwmpProtocol::FailedDestination>::const_iterator i = failedDe
stinations.begin (); i |
| 327 != failedDestinations.end (); i++) |
| 328 { |
| 329 if (!perr->IsFull ()) |
| 330 { |
| 331 perr->AddAddressUnit (*i); |
| 332 } |
| 333 else |
| 334 { |
| 335 elements.AddInformationElement(perr); |
| 336 perr->ResetPerr (); |
| 337 } |
| 338 } |
| 339 if (perr->GetNumOfDest () > 0) |
| 340 { |
| 341 elements.AddInformationElement(perr); |
| 342 } |
| 343 packet->AddHeader (elements); |
| 344 packet->AddHeader (GetWifiMeshActionHeader ()); |
| 345 //create 802.11 header: |
| 346 WifiMacHeader hdr; |
| 347 hdr.SetAction (); |
| 348 hdr.SetDsNotFrom (); |
| 349 hdr.SetDsNotTo (); |
| 350 hdr.SetAddr2 (m_parent->GetAddress ()); |
| 351 hdr.SetAddr3 (m_protocol->GetAddress ()); |
| 352 if (receivers.size () >= m_protocol->GetUnicastPerrThreshold ()) |
| 353 { |
| 354 receivers.clear (); |
| 355 receivers.push_back (Mac48Address::GetBroadcast ()); |
| 356 } |
| 357 //Send Management frame |
| 358 for (std::vector<Mac48Address>::const_iterator i = receivers.begin (); i != re
ceivers.end (); i++) |
| 359 { |
| 360 hdr.SetAddr1 (*i); |
| 361 m_stats.txPerr++; |
| 362 m_stats.txMgt++; |
| 363 m_stats.txMgtBytes += packet->GetSize (); |
| 364 m_parent->SendManagementFrame (packet, hdr); |
| 365 } |
| 366 } |
| 367 void |
| 368 HwmpProtocolMac::InitiatePerr (std::vector<HwmpProtocol::FailedDestination> fail
edDestinations, std::vector< |
| 369 Mac48Address> receivers) |
| 370 { |
| 371 //All duplicates in PERR are checked here, and there is no reason to |
| 372 //check it at any athoer place |
| 373 { |
| 374 std::vector<Mac48Address>::const_iterator end = receivers.end (); |
| 375 for (std::vector<Mac48Address>::const_iterator i = receivers.begin (); i !
= end; i++) |
| 376 { |
| 377 bool should_add = true; |
| 378 for (std::vector<Mac48Address>::const_iterator j = m_myPerr.receivers.
begin (); j |
| 379 != m_myPerr.receivers.end (); j++) |
| 380 { |
| 381 if ((*i) == (*j)) |
| 382 { |
| 383 should_add = false; |
| 384 } |
| 385 } |
| 386 if (should_add) |
| 387 { |
| 388 m_myPerr.receivers.push_back (*i); |
| 389 } |
| 390 } |
| 391 } |
| 392 { |
| 393 std::vector<HwmpProtocol::FailedDestination>::const_iterator end = failedD
estinations.end (); |
| 394 for (std::vector<HwmpProtocol::FailedDestination>::const_iterator i = fail
edDestinations.begin (); i != end; i++) |
| 395 { |
| 396 bool should_add = true; |
| 397 for (std::vector<HwmpProtocol::FailedDestination>::const_iterator j =
m_myPerr.destinations.begin (); j |
| 398 != m_myPerr.destinations.end (); j++) |
| 399 { |
| 400 if (((*i).destination == (*j).destination) && ((*j).seqnum > (*i).
seqnum)) |
| 401 { |
| 402 should_add = false; |
| 403 } |
| 404 } |
| 405 if (should_add) |
| 406 { |
| 407 m_myPerr.destinations.push_back (*i); |
| 408 } |
| 409 } |
| 410 } |
| 411 SendMyPerr (); |
| 412 } |
| 413 void |
| 414 HwmpProtocolMac::SendMyPerr () |
| 415 { |
| 416 NS_LOG_FUNCTION_NOARGS (); |
| 417 if (m_perrTimer.IsRunning ()) |
| 418 { |
| 419 return; |
| 420 } |
| 421 m_perrTimer = Simulator::Schedule (m_protocol->GetPerrMinInterval (), &HwmpPro
tocolMac::SendMyPerr, this); |
| 422 ForwardPerr (m_myPerr.destinations, m_myPerr.receivers); |
| 423 m_myPerr.destinations.clear (); |
| 424 m_myPerr.receivers.clear (); |
| 425 } |
| 426 uint32_t |
| 427 HwmpProtocolMac::GetLinkMetric (Mac48Address peerAddress) const |
| 428 { |
| 429 return m_parent->GetLinkMetric (peerAddress); |
| 430 } |
| 431 uint16_t |
| 432 HwmpProtocolMac::GetChannelId () const |
| 433 { |
| 434 return m_parent->GetFrequencyChannel (); |
| 435 } |
| 436 HwmpProtocolMac::Statistics::Statistics () : |
| 437 txPreq (0), rxPreq (0), txPrep (0), rxPrep (0), txPerr (0), rxPerr (0), txMgt
(0), txMgtBytes (0), |
| 438 rxMgt (0), rxMgtBytes (0), txData (0), txDataBytes (0), rxData (0), rxData
Bytes (0) |
| 439 { |
| 440 } |
| 441 void |
| 442 HwmpProtocolMac::Statistics::Print (std::ostream & os) const |
| 443 { |
| 444 os << "<Statistics " |
| 445 "txPreq= \"" << txPreq << "\"" << std::endl << |
| 446 "txPrep=\"" << txPrep << "\"" << std::endl << |
| 447 "txPerr=\"" << txPerr << "\"" << std::endl << |
| 448 "rxPreq=\"" << rxPreq << "\"" << std::endl << |
| 449 "rxPrep=\"" << rxPrep << "\"" << std::endl << |
| 450 "rxPerr=\"" << rxPerr << "\"" << std::endl << |
| 451 "txMgt=\"" << txMgt << "\"" << std::endl << |
| 452 "txMgtBytes=\"" << txMgtBytes << "\"" << std::endl << |
| 453 "rxMgt=\"" << rxMgt << "\"" << std::endl << |
| 454 "rxMgtBytes=\"" << rxMgtBytes << "\"" << std::endl << |
| 455 "txData=\"" << txData << "\"" << std::endl << |
| 456 "txDataBytes=\"" << txDataBytes << "\"" << std::endl << |
| 457 "rxData=\"" << rxData << "\"" << std::endl << |
| 458 "rxDataBytes=\"" << rxDataBytes << "\"/>" << std::endl; |
| 459 } |
| 460 void |
| 461 HwmpProtocolMac::Report (std::ostream & os) const |
| 462 { |
| 463 os << "<HwmpProtocolMac" << std::endl << |
| 464 "address =\"" << m_parent->GetAddress () << "\">" << std::endl; |
| 465 m_stats.Print (os); |
| 466 os << "</HwmpProtocolMac>" << std::endl; |
| 467 } |
| 468 void |
| 469 HwmpProtocolMac::ResetStats () |
| 470 { |
| 471 m_stats = Statistics::Statistics (); |
| 472 } |
| 473 |
| 474 } //namespace dot11s |
| 475 }//namespace ns3 |
OLD | NEW |