A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
hwmp-protocol-mac.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2008,2009 IITP RAS
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Author: Kirill Andreev <andreev@iitp.ru>
18 */
19
20#include "hwmp-protocol-mac.h"
21
22#include "dot11s-mac-header.h"
23#include "hwmp-tag.h"
24#include "ie-dot11s-perr.h"
25#include "ie-dot11s-prep.h"
26#include "ie-dot11s-preq.h"
27#include "ie-dot11s-rann.h"
28
29#include "ns3/log.h"
30#include "ns3/mesh-wifi-interface-mac.h"
31#include "ns3/nstime.h"
32#include "ns3/packet.h"
33#include "ns3/simulator.h"
34#include "ns3/wifi-mac-header.h"
35
36namespace ns3
37{
38
39NS_LOG_COMPONENT_DEFINE("HwmpProtocolMac");
40
41namespace dot11s
42{
43
45 : m_ifIndex(ifIndex),
46 m_protocol(protocol)
47{
48 NS_LOG_FUNCTION(this << ifIndex << protocol);
49}
50
52{
53}
54
55void
57{
58 NS_LOG_FUNCTION(this << parent);
59 m_parent = parent;
60}
61
62bool
64{
65 NS_LOG_FUNCTION(this << packet << header);
66 NS_ASSERT(header.IsData());
67
68 MeshHeader meshHdr;
69 HwmpTag tag;
70 if (packet->PeekPacketTag(tag))
71 {
72 NS_FATAL_ERROR("HWMP tag is not supposed to be received by network");
73 }
74
75 packet->RemoveHeader(meshHdr);
77 m_stats.rxDataBytes += packet->GetSize();
78
80 Mac48Address destination;
81 Mac48Address source;
82 switch (meshHdr.GetAddressExt())
83 {
84 case 0:
85 source = header.GetAddr4();
86 destination = header.GetAddr3();
87 break;
88 default:
89 NS_FATAL_ERROR("6-address scheme is not yet supported and 4-address extension is not "
90 "supposed to be used for data frames.");
91 }
92 tag.SetSeqno(meshHdr.GetMeshSeqno());
93 tag.SetTtl(meshHdr.GetMeshTtl());
94 packet->AddPacketTag(tag);
95
96 if ((destination == Mac48Address::GetBroadcast()) &&
97 (m_protocol->DropDataFrame(meshHdr.GetMeshSeqno(), source)))
98 {
99 NS_LOG_DEBUG("Dropping frame; source " << source << " dest " << destination << " seqno "
100 << meshHdr.GetMeshSeqno());
101 return false;
102 }
103 return true;
104}
105
106bool
108{
109 NS_LOG_FUNCTION(this << packet << header);
110 m_stats.rxMgt++;
111 m_stats.rxMgtBytes += packet->GetSize();
112 WifiActionHeader actionHdr;
113 packet->RemoveHeader(actionHdr);
114 if (actionHdr.GetCategory() != WifiActionHeader::MESH)
115 {
116 return true;
117 }
119 // To determine header size here, we can rely on the knowledge that
120 // this is the last header to remove.
121 packet->RemoveHeader(elements, packet->GetSize());
122 std::vector<HwmpProtocol::FailedDestination> failedDestinations;
123 for (auto i = elements.Begin(); i != elements.End(); i++)
124 {
125 if ((*i)->ElementId() == IE_RANN)
126 {
127 NS_LOG_WARN("RANN is not supported!");
128 }
129 if ((*i)->ElementId() == IE_PREQ)
130 {
131 Ptr<IePreq> preq = DynamicCast<IePreq>(*i);
132 NS_ASSERT(preq);
133 m_stats.rxPreq++;
134 if (preq->GetOriginatorAddress() == m_protocol->GetAddress())
135 {
136 continue;
137 }
138 if (preq->GetTtl() == 0)
139 {
140 continue;
141 }
142 preq->DecrementTtl();
143 m_protocol->ReceivePreq(*preq,
144 header.GetAddr2(),
145 m_ifIndex,
146 header.GetAddr3(),
147 m_parent->GetLinkMetric(header.GetAddr2()));
148 }
149 if ((*i)->ElementId() == IE_PREP)
150 {
151 Ptr<IePrep> prep = DynamicCast<IePrep>(*i);
152 NS_ASSERT(prep);
153 m_stats.rxPrep++;
154 if (prep->GetTtl() == 0)
155 {
156 continue;
157 }
158 prep->DecrementTtl();
159 m_protocol->ReceivePrep(*prep,
160 header.GetAddr2(),
161 m_ifIndex,
162 header.GetAddr3(),
163 m_parent->GetLinkMetric(header.GetAddr2()));
164 }
165 if ((*i)->ElementId() == IE_PERR)
166 {
167 Ptr<IePerr> perr = DynamicCast<IePerr>(*i);
168 NS_ASSERT(perr);
169 m_stats.rxPerr++;
170 std::vector<HwmpProtocol::FailedDestination> destinations =
171 perr->GetAddressUnitVector();
172 for (auto i = destinations.begin(); i != destinations.end(); i++)
173 {
174 failedDestinations.push_back(*i);
175 }
176 }
177 }
178 if (!failedDestinations.empty())
179 {
180 m_protocol->ReceivePerr(failedDestinations,
181 header.GetAddr2(),
182 m_ifIndex,
183 header.GetAddr3());
184 }
185 NS_ASSERT(packet->GetSize() == 0);
186 return false;
187}
188
189bool
191{
192 NS_LOG_FUNCTION(this << packet << header);
193 if (header.IsData())
194 {
195 return ReceiveData(packet, header);
196 }
197 else
198 {
199 if (header.IsAction())
200 {
201 return ReceiveAction(packet, header);
202 }
203 else
204 {
205 return true; // don't care
206 }
207 }
208}
209
210bool
212 WifiMacHeader& header,
213 Mac48Address from,
214 Mac48Address to)
215{
216 NS_LOG_FUNCTION(this << packet << header << from << to);
217 if (!header.IsData())
218 {
219 return true;
220 }
221 HwmpTag tag;
222 bool tagExists = packet->RemovePacketTag(tag);
223 if (!tagExists)
224 {
225 NS_FATAL_ERROR("HWMP tag must exist at this point");
226 }
227 m_stats.txData++;
228 m_stats.txDataBytes += packet->GetSize();
229 MeshHeader meshHdr;
230 meshHdr.SetMeshSeqno(tag.GetSeqno());
231 meshHdr.SetMeshTtl(tag.GetTtl());
232 packet->AddHeader(meshHdr);
233 header.SetAddr1(tag.GetAddress());
235 return true;
236}
237
240{
241 WifiActionHeader actionHdr;
243 action.meshAction = WifiActionHeader::PATH_SELECTION;
244 actionHdr.SetAction(WifiActionHeader::MESH, action);
245 return actionHdr;
246}
247
248void
250{
251 NS_LOG_FUNCTION(this);
252 std::vector<IePreq> preq_vector;
253 preq_vector.push_back(preq);
254 SendPreqVector(preq_vector);
255}
256
257void
258HwmpProtocolMac::SendPreqVector(std::vector<IePreq> preq)
259{
260 NS_LOG_FUNCTION(this);
261 Ptr<Packet> packet = Create<Packet>();
263 for (auto i = preq.begin(); i != preq.end(); i++)
264 {
265 elements.AddInformationElement(Ptr<IePreq>(&(*i)));
266 }
267 packet->AddHeader(elements);
268 packet->AddHeader(GetWifiActionHeader());
269 // create 802.11 header:
270 WifiMacHeader hdr;
272 hdr.SetDsNotFrom();
273 hdr.SetDsNotTo();
274 hdr.SetAddr2(m_parent->GetAddress());
275 hdr.SetAddr3(m_protocol->GetAddress());
276 // Send Management frame
277 std::vector<Mac48Address> receivers = m_protocol->GetPreqReceivers(m_ifIndex);
278 for (auto i = receivers.begin(); i != receivers.end(); i++)
279 {
280 hdr.SetAddr1(*i);
281 m_stats.txPreq++;
282 m_stats.txMgt++;
283 m_stats.txMgtBytes += packet->GetSize();
284 m_parent->SendManagementFrame(packet, hdr);
285 }
286}
287
288void
290{
291 NS_LOG_FUNCTION(this << dst << originator_seqno << dst_seqno);
292 for (auto i = m_myPreq.begin(); i != m_myPreq.end(); i++)
293 {
294 if (i->IsFull())
295 {
296 continue;
297 }
298 NS_ASSERT(i->GetDestCount() > 0);
299 i->AddDestinationAddressElement(m_protocol->GetDoFlag(),
300 m_protocol->GetRfFlag(),
301 dst,
302 dst_seqno);
303 }
304 IePreq preq;
305 preq.SetHopcount(0);
306 preq.SetTTL(m_protocol->GetMaxTtl());
307 preq.SetPreqID(m_protocol->GetNextPreqId());
308 preq.SetOriginatorAddress(m_protocol->GetAddress());
309 preq.SetOriginatorSeqNumber(originator_seqno);
310 preq.SetLifetime(m_protocol->GetActivePathLifetime());
312 m_protocol->GetRfFlag(),
313 dst,
314 dst_seqno);
315 m_myPreq.push_back(preq);
316 SendMyPreq();
317}
318
319void
321{
322 NS_LOG_FUNCTION(this);
324 {
325 return;
326 }
327 if (m_myPreq.empty())
328 {
329 return;
330 }
331 // reschedule sending PREQ
334 Simulator::Schedule(m_protocol->GetPreqMinInterval(), &HwmpProtocolMac::SendMyPreq, this);
336 m_myPreq.clear();
337}
338
339void
341{
342 NS_LOG_FUNCTION(this << receiver);
343 // Create packet
344 Ptr<Packet> packet = Create<Packet>();
346 elements.AddInformationElement(Ptr<IePrep>(&prep));
347 packet->AddHeader(elements);
348 packet->AddHeader(GetWifiActionHeader());
349 // create 802.11 header:
350 WifiMacHeader hdr;
352 hdr.SetDsNotFrom();
353 hdr.SetDsNotTo();
354 hdr.SetAddr1(receiver);
355 hdr.SetAddr2(m_parent->GetAddress());
356 hdr.SetAddr3(m_protocol->GetAddress());
357 // Send Management frame
358 m_stats.txPrep++;
359 m_stats.txMgt++;
360 m_stats.txMgtBytes += packet->GetSize();
361 m_parent->SendManagementFrame(packet, hdr);
362}
363
364void
365HwmpProtocolMac::ForwardPerr(std::vector<HwmpProtocol::FailedDestination> failedDestinations,
366 std::vector<Mac48Address> receivers)
367{
368 NS_LOG_FUNCTION(this);
369 Ptr<Packet> packet = Create<Packet>();
370 Ptr<IePerr> perr = Create<IePerr>();
372 for (auto i = failedDestinations.begin(); i != failedDestinations.end(); i++)
373 {
374 if (!perr->IsFull())
375 {
376 perr->AddAddressUnit(*i);
377 }
378 else
379 {
380 elements.AddInformationElement(perr);
381 perr->ResetPerr();
382 }
383 }
384 if (perr->GetNumOfDest() > 0)
385 {
386 elements.AddInformationElement(perr);
387 }
388 packet->AddHeader(elements);
389 packet->AddHeader(GetWifiActionHeader());
390 // create 802.11 header:
391 WifiMacHeader hdr;
393 hdr.SetDsNotFrom();
394 hdr.SetDsNotTo();
395 hdr.SetAddr2(m_parent->GetAddress());
396 hdr.SetAddr3(m_protocol->GetAddress());
397 if (receivers.size() >= m_protocol->GetUnicastPerrThreshold())
398 {
399 receivers.clear();
400 receivers.push_back(Mac48Address::GetBroadcast());
401 }
402 // Send Management frame
403 for (auto i = receivers.begin(); i != receivers.end(); i++)
404 {
405 //
406 // 64-bit Intel valgrind complains about hdr.SetAddr1 (*i). It likes this
407 // just fine.
408 //
409 Mac48Address address = *i;
410 hdr.SetAddr1(address);
411 m_stats.txPerr++;
412 m_stats.txMgt++;
413 m_stats.txMgtBytes += packet->GetSize();
414 m_parent->SendManagementFrame(packet, hdr);
415 }
416}
417
418void
419HwmpProtocolMac::InitiatePerr(std::vector<HwmpProtocol::FailedDestination> failedDestinations,
420 std::vector<Mac48Address> receivers)
421{
422 NS_LOG_FUNCTION(this);
423 // All duplicates in PERR are checked here, and there is no reason to
424 // check it at any other place
425 {
426 for (auto i = receivers.begin(); i != receivers.end(); i++)
427 {
428 bool should_add = true;
429 for (auto j = m_myPerr.receivers.begin(); j != m_myPerr.receivers.end(); j++)
430 {
431 if ((*i) == (*j))
432 {
433 should_add = false;
434 }
435 }
436 if (should_add)
437 {
438 m_myPerr.receivers.push_back(*i);
439 NS_LOG_DEBUG("Initiate PERR: Adding receiver: " << (*i));
440 }
441 }
442 }
443 {
444 for (auto i = failedDestinations.begin(); i != failedDestinations.end(); i++)
445 {
446 bool should_add = true;
447 for (auto j = m_myPerr.destinations.begin(); j != m_myPerr.destinations.end(); j++)
448 {
449 if (((*i).destination == (*j).destination) && ((*j).seqnum > (*i).seqnum))
450 {
451 should_add = false;
452 }
453 }
454 if (should_add)
455 {
456 m_myPerr.destinations.push_back(*i);
457 NS_LOG_DEBUG("Initiate PERR: Adding failed destination: " << (*i).destination);
458 }
459 }
460 }
461 SendMyPerr();
462}
463
464void
466{
467 NS_LOG_FUNCTION(this);
469 {
470 return;
471 }
473 Simulator::Schedule(m_protocol->GetPerrMinInterval(), &HwmpProtocolMac::SendMyPerr, this);
475 m_myPerr.destinations.clear();
476 m_myPerr.receivers.clear();
477}
478
481{
482 return m_parent->GetLinkMetric(peerAddress);
483}
484
485uint16_t
487{
488 return m_parent->GetFrequencyChannel();
489}
490
492 : txPreq(0),
493 rxPreq(0),
494 txPrep(0),
495 rxPrep(0),
496 txPerr(0),
497 rxPerr(0),
498 txMgt(0),
499 txMgtBytes(0),
500 rxMgt(0),
501 rxMgtBytes(0),
502 txData(0),
503 txDataBytes(0),
504 rxData(0),
505 rxDataBytes(0)
506{
507}
508
509void
511{
512 os << "<Statistics "
513 "txPreq= \""
514 << txPreq << "\"" << std::endl
515 << "txPrep=\"" << txPrep << "\"" << std::endl
516 << "txPerr=\"" << txPerr << "\"" << std::endl
517 << "rxPreq=\"" << rxPreq << "\"" << std::endl
518 << "rxPrep=\"" << rxPrep << "\"" << std::endl
519 << "rxPerr=\"" << rxPerr << "\"" << std::endl
520 << "txMgt=\"" << txMgt << "\"" << std::endl
521 << "txMgtBytes=\"" << txMgtBytes << "\"" << std::endl
522 << "rxMgt=\"" << rxMgt << "\"" << std::endl
523 << "rxMgtBytes=\"" << rxMgtBytes << "\"" << std::endl
524 << "txData=\"" << txData << "\"" << std::endl
525 << "txDataBytes=\"" << txDataBytes << "\"" << std::endl
526 << "rxData=\"" << rxData << "\"" << std::endl
527 << "rxDataBytes=\"" << rxDataBytes << "\"/>" << std::endl;
528}
529
530void
531HwmpProtocolMac::Report(std::ostream& os) const
532{
533 os << "<HwmpProtocolMac" << std::endl
534 << "address =\"" << m_parent->GetAddress() << "\">" << std::endl;
535 m_stats.Print(os);
536 os << "</HwmpProtocolMac>" << std::endl;
537}
538
539void
541{
542 NS_LOG_FUNCTION(this);
544}
545
546int64_t
548{
549 return m_protocol->AssignStreams(stream);
550}
551
552} // namespace dot11s
553} // namespace ns3
bool IsRunning() const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:76
an EUI-48 address
Definition: mac48-address.h:46
static Mac48Address GetBroadcast()
Iterator End()
Returns End of the vector.
bool AddInformationElement(Ptr< WifiInformationElement > element)
add an IE, if maxSize has exceeded, returns false
Iterator Begin()
Returns Begin of the vector.
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:558
See IEEE 802.11 chapter 7.3.1.11 Header format: | category: 1 | action value: 1 |.
Definition: mgt-headers.h:539
void SetAction(CategoryValue type, ActionValue action)
Set action for this Action header.
Definition: mgt-headers.cc:601
CategoryValue GetCategory() const
Return the category value.
Definition: mgt-headers.cc:658
Implements the IEEE 802.11 MAC header.
Mac48Address GetAddr3() const
Return the address in the Address 3 field.
Mac48Address GetAddr4() const
Return the address in the Address 4 field.
void SetDsNotFrom()
Un-set the From DS bit in the Frame Control field.
bool IsAction() const
Return true if the header is an Action header.
void SetAddr1(Mac48Address address)
Fill the Address 1 field with the given address.
virtual void SetType(WifiMacType type, bool resetToDsFromDs=true)
Set Type/Subtype values with the correct values depending on the given type.
Mac48Address GetAddr2() const
Return the address in the Address 2 field.
bool IsData() const
Return true if the Type is DATA.
void SetAddr2(Mac48Address address)
Fill the Address 2 field with the given address.
void SetAddr3(Mac48Address address)
Fill the Address 3 field with the given address.
void SetDsNotTo()
Un-set the To DS bit in the Frame Control field.
void SetQosMeshControlPresent()
Set the Mesh Control Present flag for the QoS header.
static WifiActionHeader GetWifiActionHeader()
void SendMyPreq()
Sends one PREQ when PreqMinInterval after last PREQ expires (if any PREQ exists in rhe queue)
void SendPreq(IePreq preq)
Send PREQ function.
HwmpProtocolMac(uint32_t ifIndex, Ptr< HwmpProtocol > protocol)
Constructor.
void SetParent(Ptr< MeshWifiInterfaceMac > parent) override
Each plugin must be installed on an interface to work.
void SendPreqVector(std::vector< IePreq > preq)
Send PREQ function for vector of PREQ.
void SendPrep(IePrep prep, Mac48Address receiver)
Send PREP function.
void SendMyPerr()
Send PERR function.
uint16_t GetChannelId() const
Get the channel ID.
bool Receive(Ptr< Packet > packet, const WifiMacHeader &header) override
Process received frame.
void ForwardPerr(std::vector< HwmpProtocol::FailedDestination > destinations, std::vector< Mac48Address > receivers)
Forward a path error.
Ptr< HwmpProtocol > m_protocol
protocol
bool ReceiveData(Ptr< Packet > packet, const WifiMacHeader &header)
Receive data frame.
Statistics m_stats
statistics
EventId m_preqTimer
Timer for PREQs.
void ResetStats()
Reset statistics.
uint32_t GetLinkMetric(Mac48Address peerAddress) const
bool ReceiveAction(Ptr< Packet > packet, const WifiMacHeader &header)
Receive action management frame.
void InitiatePerr(std::vector< HwmpProtocol::FailedDestination > destinations, std::vector< Mac48Address > receivers)
initiate my own path error
int64_t AssignStreams(int64_t stream) override
Assign a fixed random variable stream number to the random variables used by this model.
std::vector< IePreq > m_myPreq
container of PREQs
void Report(std::ostream &os) const
Report statistics.
bool UpdateOutcomingFrame(Ptr< Packet > packet, WifiMacHeader &header, Mac48Address from, Mac48Address to) override
Update frame before it will be forwarded down.
Ptr< MeshWifiInterfaceMac > m_parent
parent
void RequestDestination(Mac48Address dest, uint32_t originator_seqno, uint32_t dst_seqno)
Request a destination.
Hwmp tag implements interaction between HWMP protocol and MeshWifiMac.
Definition: hwmp-tag.h:51
void SetTtl(uint8_t ttl)
Set the TTL value.
Definition: hwmp-tag.cc:55
uint32_t GetSeqno() const
Get the sequence number.
Definition: hwmp-tag.cc:85
void SetSeqno(uint32_t seqno)
Set sequence number.
Definition: hwmp-tag.cc:79
uint8_t GetTtl() const
Get the TTL value.
Definition: hwmp-tag.cc:61
Mac48Address GetAddress()
Get address from tag.
Definition: hwmp-tag.cc:49
See 7.3.2.97 of 802.11s draft 2.07.
See 7.3.2.96 of 802.11s draft 2.07.
void SetHopcount(uint8_t hopcount)
Set number of hops from originator to mesh STA transmitting this element.
void SetOriginatorSeqNumber(uint32_t originator_seq_number)
Set originator sequence number.
void SetTTL(uint8_t ttl)
Set remaining number of hops allowed for this element.
void SetOriginatorAddress(Mac48Address originator_address)
Set originator address value.
void SetPreqID(uint32_t id)
Set path discovery id field.
void AddDestinationAddressElement(bool doFlag, bool rfFlag, Mac48Address dest_address, uint32_t dest_seq_number)
Add a destination address unit: flags, destination and sequence number.
void SetLifetime(uint32_t lifetime)
Set lifetime in TUs for the forwarding information to be considered valid.
Mesh Control field, see Section 8.2.4.7.3 IEEE 802.11-2012.
void SetMeshSeqno(uint32_t seqno)
Set four-byte mesh sequence number.
uint32_t GetMeshSeqno() const
Get the four-byte mesh sequence number.
void SetMeshTtl(uint8_t TTL)
Set mesh TTL subfield corresponding to the remaining number of hops the MSDU/MMPDU is forwarded.
uint8_t GetAddressExt() const
Get Address Extension Mode.
uint8_t GetMeshTtl() const
Get mesh TTL function subfield value.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:261
Every class exported by the ns3 library is enclosed in the ns3 namespace.
@ WIFI_MAC_MGT_ACTION
std::vector< HwmpProtocol::FailedDestination > destinations
destinations
std::vector< Mac48Address > receivers
receivers
uint32_t txMgtBytes
transmit management bytes
void Print(std::ostream &os) const
Print function.
uint32_t txDataBytes
transmit data bytes
uint32_t rxMgtBytes
receive management bytes
typedef for union of different ActionValues
Definition: mgt-headers.h:723
#define IE_PREQ
#define IE_RANN
#define IE_PREP
#define IE_PERR