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 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Kirill Andreev <andreev@iitp.ru>
7 */
8
9#include "hwmp-protocol-mac.h"
10
11#include "dot11s-mac-header.h"
12#include "hwmp-tag.h"
13#include "ie-dot11s-perr.h"
14#include "ie-dot11s-prep.h"
15#include "ie-dot11s-preq.h"
16#include "ie-dot11s-rann.h"
17
18#include "ns3/log.h"
19#include "ns3/mesh-wifi-interface-mac.h"
20#include "ns3/mgt-action-headers.h"
21#include "ns3/nstime.h"
22#include "ns3/packet.h"
23#include "ns3/simulator.h"
24#include "ns3/wifi-mac-header.h"
25
26namespace ns3
27{
28
29NS_LOG_COMPONENT_DEFINE("HwmpProtocolMac");
30
31namespace dot11s
32{
33
35 : m_ifIndex(ifIndex),
36 m_protocol(protocol)
37{
38 NS_LOG_FUNCTION(this << ifIndex << protocol);
39}
40
44
45void
47{
48 NS_LOG_FUNCTION(this << parent);
49 m_parent = parent;
50}
51
52bool
54{
55 NS_LOG_FUNCTION(this << packet << header);
56 NS_ASSERT(header.IsData());
57
58 MeshHeader meshHdr;
59 HwmpTag tag;
60 if (packet->PeekPacketTag(tag))
61 {
62 NS_FATAL_ERROR("HWMP tag is not supposed to be received by network");
63 }
64
65 packet->RemoveHeader(meshHdr);
67 m_stats.rxDataBytes += packet->GetSize();
68
69 /// @todo address extension
70 Mac48Address destination;
71 Mac48Address source;
72 switch (meshHdr.GetAddressExt())
73 {
74 case 0:
75 source = header.GetAddr4();
76 destination = header.GetAddr3();
77 break;
78 default:
79 NS_FATAL_ERROR("6-address scheme is not yet supported and 4-address extension is not "
80 "supposed to be used for data frames.");
81 }
82 tag.SetSeqno(meshHdr.GetMeshSeqno());
83 tag.SetTtl(meshHdr.GetMeshTtl());
84 packet->AddPacketTag(tag);
85
86 if ((destination == Mac48Address::GetBroadcast()) &&
87 (m_protocol->DropDataFrame(meshHdr.GetMeshSeqno(), source)))
88 {
89 NS_LOG_DEBUG("Dropping frame; source " << source << " dest " << destination << " seqno "
90 << meshHdr.GetMeshSeqno());
91 return false;
92 }
93 return true;
94}
95
96bool
98{
99 NS_LOG_FUNCTION(this << packet << header);
100 m_stats.rxMgt++;
101 m_stats.rxMgtBytes += packet->GetSize();
102 WifiActionHeader actionHdr;
103 packet->RemoveHeader(actionHdr);
104 if (actionHdr.GetCategory() != WifiActionHeader::MESH)
105 {
106 return true;
107 }
109 // To determine header size here, we can rely on the knowledge that
110 // this is the last header to remove.
111 packet->RemoveHeader(elements, packet->GetSize());
112 std::vector<HwmpProtocol::FailedDestination> failedDestinations;
113 for (auto i = elements.Begin(); i != elements.End(); i++)
114 {
115 if ((*i)->ElementId() == IE_RANN)
116 {
117 NS_LOG_WARN("RANN is not supported!");
118 }
119 if ((*i)->ElementId() == IE_PREQ)
120 {
122 NS_ASSERT(preq);
123 m_stats.rxPreq++;
124 if (preq->GetOriginatorAddress() == m_protocol->GetAddress())
125 {
126 continue;
127 }
128 if (preq->GetTtl() == 0)
129 {
130 continue;
131 }
132 preq->DecrementTtl();
133 m_protocol->ReceivePreq(*preq,
134 header.GetAddr2(),
135 m_ifIndex,
136 header.GetAddr3(),
137 m_parent->GetLinkMetric(header.GetAddr2()));
138 }
139 if ((*i)->ElementId() == IE_PREP)
140 {
142 NS_ASSERT(prep);
143 m_stats.rxPrep++;
144 if (prep->GetTtl() == 0)
145 {
146 continue;
147 }
148 prep->DecrementTtl();
149 m_protocol->ReceivePrep(*prep,
150 header.GetAddr2(),
151 m_ifIndex,
152 header.GetAddr3(),
153 m_parent->GetLinkMetric(header.GetAddr2()));
154 }
155 if ((*i)->ElementId() == IE_PERR)
156 {
158 NS_ASSERT(perr);
159 m_stats.rxPerr++;
160 std::vector<HwmpProtocol::FailedDestination> destinations =
161 perr->GetAddressUnitVector();
162 for (auto i = destinations.begin(); i != destinations.end(); i++)
163 {
164 failedDestinations.push_back(*i);
165 }
166 }
167 }
168 if (!failedDestinations.empty())
169 {
170 m_protocol->ReceivePerr(failedDestinations,
171 header.GetAddr2(),
172 m_ifIndex,
173 header.GetAddr3());
174 }
175 NS_ASSERT(packet->GetSize() == 0);
176 return false;
177}
178
179bool
181{
182 NS_LOG_FUNCTION(this << packet << header);
183 if (header.IsData())
184 {
185 return ReceiveData(packet, header);
186 }
187 else
188 {
189 if (header.IsAction())
190 {
191 return ReceiveAction(packet, header);
192 }
193 else
194 {
195 return true; // don't care
196 }
197 }
198}
199
200bool
202 WifiMacHeader& header,
203 Mac48Address from,
204 Mac48Address to)
205{
206 NS_LOG_FUNCTION(this << packet << header << from << to);
207 if (!header.IsData())
208 {
209 return true;
210 }
211 HwmpTag tag;
212 bool tagExists = packet->RemovePacketTag(tag);
213 if (!tagExists)
214 {
215 NS_FATAL_ERROR("HWMP tag must exist at this point");
216 }
217 m_stats.txData++;
218 m_stats.txDataBytes += packet->GetSize();
219 MeshHeader meshHdr;
220 meshHdr.SetMeshSeqno(tag.GetSeqno());
221 meshHdr.SetMeshTtl(tag.GetTtl());
222 packet->AddHeader(meshHdr);
223 header.SetAddr1(tag.GetAddress());
225 return true;
226}
227
230{
231 WifiActionHeader actionHdr;
233 action.meshAction = WifiActionHeader::PATH_SELECTION;
234 actionHdr.SetAction(WifiActionHeader::MESH, action);
235 return actionHdr;
236}
237
238void
240{
241 NS_LOG_FUNCTION(this);
242 std::vector<IePreq> preq_vector;
243 preq_vector.push_back(preq);
244 SendPreqVector(preq_vector);
245}
246
247void
248HwmpProtocolMac::SendPreqVector(std::vector<IePreq> preq)
249{
250 NS_LOG_FUNCTION(this);
251 Ptr<Packet> packet = Create<Packet>();
253 for (auto i = preq.begin(); i != preq.end(); i++)
254 {
255 elements.AddInformationElement(Ptr<IePreq>(&(*i)));
256 }
257 packet->AddHeader(elements);
258 packet->AddHeader(GetWifiActionHeader());
259 // create 802.11 header:
260 WifiMacHeader hdr;
262 hdr.SetDsNotFrom();
263 hdr.SetDsNotTo();
264 hdr.SetAddr2(m_parent->GetAddress());
265 hdr.SetAddr3(m_protocol->GetAddress());
266 // Send Management frame
267 std::vector<Mac48Address> receivers = m_protocol->GetPreqReceivers(m_ifIndex);
268 for (auto i = receivers.begin(); i != receivers.end(); i++)
269 {
270 hdr.SetAddr1(*i);
271 m_stats.txPreq++;
272 m_stats.txMgt++;
273 m_stats.txMgtBytes += packet->GetSize();
274 m_parent->SendManagementFrame(packet, hdr);
275 }
276}
277
278void
280{
281 NS_LOG_FUNCTION(this << dst << originator_seqno << dst_seqno);
282 for (auto i = m_myPreq.begin(); i != m_myPreq.end(); i++)
283 {
284 if (i->IsFull())
285 {
286 continue;
287 }
288 NS_ASSERT(i->GetDestCount() > 0);
289 i->AddDestinationAddressElement(m_protocol->GetDoFlag(),
290 m_protocol->GetRfFlag(),
291 dst,
292 dst_seqno);
293 }
294 IePreq preq;
295 preq.SetHopcount(0);
296 preq.SetTTL(m_protocol->GetMaxTtl());
297 preq.SetPreqID(m_protocol->GetNextPreqId());
298 preq.SetOriginatorAddress(m_protocol->GetAddress());
299 preq.SetOriginatorSeqNumber(originator_seqno);
300 preq.SetLifetime(m_protocol->GetActivePathLifetime());
302 m_protocol->GetRfFlag(),
303 dst,
304 dst_seqno);
305 m_myPreq.push_back(preq);
306 SendMyPreq();
307}
308
309void
311{
312 NS_LOG_FUNCTION(this);
314 {
315 return;
316 }
317 if (m_myPreq.empty())
318 {
319 return;
320 }
321 // reschedule sending PREQ
324 Simulator::Schedule(m_protocol->GetPreqMinInterval(), &HwmpProtocolMac::SendMyPreq, this);
326 m_myPreq.clear();
327}
328
329void
331{
332 NS_LOG_FUNCTION(this << receiver);
333 // Create packet
334 Ptr<Packet> packet = Create<Packet>();
336 elements.AddInformationElement(Ptr<IePrep>(&prep));
337 packet->AddHeader(elements);
338 packet->AddHeader(GetWifiActionHeader());
339 // create 802.11 header:
340 WifiMacHeader hdr;
342 hdr.SetDsNotFrom();
343 hdr.SetDsNotTo();
344 hdr.SetAddr1(receiver);
345 hdr.SetAddr2(m_parent->GetAddress());
346 hdr.SetAddr3(m_protocol->GetAddress());
347 // Send Management frame
348 m_stats.txPrep++;
349 m_stats.txMgt++;
350 m_stats.txMgtBytes += packet->GetSize();
351 m_parent->SendManagementFrame(packet, hdr);
352}
353
354void
355HwmpProtocolMac::ForwardPerr(std::vector<HwmpProtocol::FailedDestination> failedDestinations,
356 std::vector<Mac48Address> receivers)
357{
358 NS_LOG_FUNCTION(this);
359 Ptr<Packet> packet = Create<Packet>();
362 for (auto i = failedDestinations.begin(); i != failedDestinations.end(); i++)
363 {
364 if (!perr->IsFull())
365 {
366 perr->AddAddressUnit(*i);
367 }
368 else
369 {
370 elements.AddInformationElement(perr);
371 perr->ResetPerr();
372 }
373 }
374 if (perr->GetNumOfDest() > 0)
375 {
376 elements.AddInformationElement(perr);
377 }
378 packet->AddHeader(elements);
379 packet->AddHeader(GetWifiActionHeader());
380 // create 802.11 header:
381 WifiMacHeader hdr;
383 hdr.SetDsNotFrom();
384 hdr.SetDsNotTo();
385 hdr.SetAddr2(m_parent->GetAddress());
386 hdr.SetAddr3(m_protocol->GetAddress());
387 if (receivers.size() >= m_protocol->GetUnicastPerrThreshold())
388 {
389 receivers.clear();
390 receivers.push_back(Mac48Address::GetBroadcast());
391 }
392 // Send Management frame
393 for (auto i = receivers.begin(); i != receivers.end(); i++)
394 {
395 //
396 // 64-bit Intel valgrind complains about hdr.SetAddr1 (*i). It likes this
397 // just fine.
398 //
399 Mac48Address address = *i;
400 hdr.SetAddr1(address);
401 m_stats.txPerr++;
402 m_stats.txMgt++;
403 m_stats.txMgtBytes += packet->GetSize();
404 m_parent->SendManagementFrame(packet, hdr);
405 }
406}
407
408void
409HwmpProtocolMac::InitiatePerr(std::vector<HwmpProtocol::FailedDestination> failedDestinations,
410 std::vector<Mac48Address> receivers)
411{
412 NS_LOG_FUNCTION(this);
413 // All duplicates in PERR are checked here, and there is no reason to
414 // check it at any other place
415 {
416 for (auto i = receivers.begin(); i != receivers.end(); i++)
417 {
418 bool should_add = true;
419 for (auto j = m_myPerr.receivers.begin(); j != m_myPerr.receivers.end(); j++)
420 {
421 if ((*i) == (*j))
422 {
423 should_add = false;
424 }
425 }
426 if (should_add)
427 {
428 m_myPerr.receivers.push_back(*i);
429 NS_LOG_DEBUG("Initiate PERR: Adding receiver: " << (*i));
430 }
431 }
432 }
433 {
434 for (auto i = failedDestinations.begin(); i != failedDestinations.end(); i++)
435 {
436 bool should_add = true;
437 for (auto j = m_myPerr.destinations.begin(); j != m_myPerr.destinations.end(); j++)
438 {
439 if (((*i).destination == (*j).destination) && ((*j).seqnum > (*i).seqnum))
440 {
441 should_add = false;
442 }
443 }
444 if (should_add)
445 {
446 m_myPerr.destinations.push_back(*i);
447 NS_LOG_DEBUG("Initiate PERR: Adding failed destination: " << (*i).destination);
448 }
449 }
450 }
451 SendMyPerr();
452}
453
454void
456{
457 NS_LOG_FUNCTION(this);
459 {
460 return;
461 }
463 Simulator::Schedule(m_protocol->GetPerrMinInterval(), &HwmpProtocolMac::SendMyPerr, this);
465 m_myPerr.destinations.clear();
466 m_myPerr.receivers.clear();
467}
468
471{
472 return m_parent->GetLinkMetric(peerAddress);
473}
474
475uint16_t
477{
478 return m_parent->GetFrequencyChannel();
479}
480
482 : txPreq(0),
483 rxPreq(0),
484 txPrep(0),
485 rxPrep(0),
486 txPerr(0),
487 rxPerr(0),
488 txMgt(0),
489 txMgtBytes(0),
490 rxMgt(0),
491 rxMgtBytes(0),
492 txData(0),
493 txDataBytes(0),
494 rxData(0),
495 rxDataBytes(0)
496{
497}
498
499void
501{
502 os << "<Statistics "
503 "txPreq= \""
504 << txPreq << "\"" << std::endl
505 << "txPrep=\"" << txPrep << "\"" << std::endl
506 << "txPerr=\"" << txPerr << "\"" << std::endl
507 << "rxPreq=\"" << rxPreq << "\"" << std::endl
508 << "rxPrep=\"" << rxPrep << "\"" << std::endl
509 << "rxPerr=\"" << rxPerr << "\"" << std::endl
510 << "txMgt=\"" << txMgt << "\"" << std::endl
511 << "txMgtBytes=\"" << txMgtBytes << "\"" << std::endl
512 << "rxMgt=\"" << rxMgt << "\"" << std::endl
513 << "rxMgtBytes=\"" << rxMgtBytes << "\"" << std::endl
514 << "txData=\"" << txData << "\"" << std::endl
515 << "txDataBytes=\"" << txDataBytes << "\"" << std::endl
516 << "rxData=\"" << rxData << "\"" << std::endl
517 << "rxDataBytes=\"" << rxDataBytes << "\"/>" << std::endl;
518}
519
520void
521HwmpProtocolMac::Report(std::ostream& os) const
522{
523 os << "<HwmpProtocolMac" << std::endl
524 << "address =\"" << m_parent->GetAddress() << "\">" << std::endl;
525 m_stats.Print(os);
526 os << "</HwmpProtocolMac>" << std::endl;
527}
528
529void
535
536int64_t
538{
539 return m_protocol->AssignStreams(stream);
540}
541
542} // namespace dot11s
543} // namespace ns3
bool IsPending() const
This method is syntactic sugar for !IsExpired().
Definition event-id.cc:65
an EUI-48 address
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.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:560
See IEEE 802.11 chapter 7.3.1.11 Header format: | category: 1 | action value: 1 |.
void SetAction(CategoryValue type, ActionValue action)
Set action for this Action header.
CategoryValue GetCategory() const
Return the category value.
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.
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:40
void SetTtl(uint8_t ttl)
Set the TTL value.
Definition hwmp-tag.cc:44
uint32_t GetSeqno() const
Get the sequence number.
Definition hwmp-tag.cc:74
void SetSeqno(uint32_t seqno)
Set sequence number.
Definition hwmp-tag.cc:68
uint8_t GetTtl() const
Get the TTL value.
Definition hwmp-tag.cc:50
Mac48Address GetAddress()
Get address from tag.
Definition hwmp-tag.cc:38
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:55
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
#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:250
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:436
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:580
@ 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 rxMgtBytes
receive management bytes
typedef for union of different ActionValues
#define IE_PREQ
#define IE_RANN
#define IE_PREP
#define IE_PERR