--- a/bindings/python/ns3_module_common.py Tue Apr 21 12:32:55 2009 +0200
+++ b/bindings/python/ns3_module_common.py Tue Apr 21 16:22:45 2009 +0400
@@ -9,6 +9,16 @@
module.add_class('Buffer')
## buffer.h: ns3::Buffer::Iterator [class]
module.add_class('Iterator', outer_class=root_module['ns3::Buffer'])
+ ## packet.h: ns3::ByteTagIterator [class]
+ module.add_class('ByteTagIterator')
+ ## packet.h: ns3::ByteTagIterator::Item [class]
+ module.add_class('Item', outer_class=root_module['ns3::ByteTagIterator'])
+ ## byte-tag-list.h: ns3::ByteTagList [class]
+ module.add_class('ByteTagList')
+ ## byte-tag-list.h: ns3::ByteTagList::Iterator [class]
+ module.add_class('Iterator', outer_class=root_module['ns3::ByteTagList'])
+ ## byte-tag-list.h: ns3::ByteTagList::Iterator::Item [struct]
+ module.add_class('Item', outer_class=root_module['ns3::ByteTagList::Iterator'])
## data-rate.h: ns3::DataRate [class]
module.add_class('DataRate')
## packet.h: ns3::Packet [class]
@@ -21,20 +31,18 @@
module.add_enum('', ['PAYLOAD', 'HEADER', 'TRAILER'], outer_class=root_module['ns3::PacketMetadata::Item'])
## packet-metadata.h: ns3::PacketMetadata::ItemIterator [class]
module.add_class('ItemIterator', outer_class=root_module['ns3::PacketMetadata'])
+ ## packet.h: ns3::PacketTagIterator [class]
+ module.add_class('PacketTagIterator')
+ ## packet.h: ns3::PacketTagIterator::Item [class]
+ module.add_class('Item', outer_class=root_module['ns3::PacketTagIterator'])
+ ## packet-tag-list.h: ns3::PacketTagList [class]
+ module.add_class('PacketTagList')
+ ## packet-tag-list.h: ns3::PacketTagList::TagData [struct]
+ module.add_class('TagData', outer_class=root_module['ns3::PacketTagList'])
## tag.h: ns3::Tag [class]
module.add_class('Tag', parent=root_module['ns3::ObjectBase'])
## tag-buffer.h: ns3::TagBuffer [class]
module.add_class('TagBuffer')
- ## packet.h: ns3::TagIterator [class]
- module.add_class('TagIterator')
- ## packet.h: ns3::TagIterator::Item [class]
- module.add_class('Item', outer_class=root_module['ns3::TagIterator'])
- ## tag-list.h: ns3::TagList [class]
- module.add_class('TagList')
- ## tag-list.h: ns3::TagList::Iterator [class]
- module.add_class('Iterator', outer_class=root_module['ns3::TagList'])
- ## tag-list.h: ns3::TagList::Iterator::Item [struct]
- module.add_class('Item', outer_class=root_module['ns3::TagList::Iterator'])
## chunk.h: ns3::Chunk [class]
module.add_class('Chunk', parent=root_module['ns3::ObjectBase'])
## data-rate.h: ns3::DataRateChecker [class]
@@ -97,18 +105,22 @@
def register_methods(root_module):
register_Ns3Buffer_methods(root_module, root_module['ns3::Buffer'])
register_Ns3BufferIterator_methods(root_module, root_module['ns3::Buffer::Iterator'])
+ register_Ns3ByteTagIterator_methods(root_module, root_module['ns3::ByteTagIterator'])
+ register_Ns3ByteTagIteratorItem_methods(root_module, root_module['ns3::ByteTagIterator::Item'])
+ register_Ns3ByteTagList_methods(root_module, root_module['ns3::ByteTagList'])
+ register_Ns3ByteTagListIterator_methods(root_module, root_module['ns3::ByteTagList::Iterator'])
+ register_Ns3ByteTagListIteratorItem_methods(root_module, root_module['ns3::ByteTagList::Iterator::Item'])
register_Ns3DataRate_methods(root_module, root_module['ns3::DataRate'])
register_Ns3Packet_methods(root_module, root_module['ns3::Packet'])
register_Ns3PacketMetadata_methods(root_module, root_module['ns3::PacketMetadata'])
register_Ns3PacketMetadataItem_methods(root_module, root_module['ns3::PacketMetadata::Item'])
register_Ns3PacketMetadataItemIterator_methods(root_module, root_module['ns3::PacketMetadata::ItemIterator'])
+ register_Ns3PacketTagIterator_methods(root_module, root_module['ns3::PacketTagIterator'])
+ register_Ns3PacketTagIteratorItem_methods(root_module, root_module['ns3::PacketTagIterator::Item'])
+ register_Ns3PacketTagList_methods(root_module, root_module['ns3::PacketTagList'])
+ register_Ns3PacketTagListTagData_methods(root_module, root_module['ns3::PacketTagList::TagData'])
register_Ns3Tag_methods(root_module, root_module['ns3::Tag'])
register_Ns3TagBuffer_methods(root_module, root_module['ns3::TagBuffer'])
- register_Ns3TagIterator_methods(root_module, root_module['ns3::TagIterator'])
- register_Ns3TagIteratorItem_methods(root_module, root_module['ns3::TagIterator::Item'])
- register_Ns3TagList_methods(root_module, root_module['ns3::TagList'])
- register_Ns3TagListIterator_methods(root_module, root_module['ns3::TagList::Iterator'])
- register_Ns3TagListIteratorItem_methods(root_module, root_module['ns3::TagList::Iterator::Item'])
register_Ns3Chunk_methods(root_module, root_module['ns3::Chunk'])
register_Ns3DataRateChecker_methods(root_module, root_module['ns3::DataRateChecker'])
register_Ns3DataRateValue_methods(root_module, root_module['ns3::DataRateValue'])
@@ -336,6 +348,113 @@
is_const=True)
return
+def register_Ns3ByteTagIterator_methods(root_module, cls):
+ ## packet.h: ns3::ByteTagIterator::ByteTagIterator(ns3::ByteTagIterator const & arg0) [copy constructor]
+ cls.add_constructor([param('ns3::ByteTagIterator const &', 'arg0')])
+ ## packet.h: bool ns3::ByteTagIterator::HasNext() const [member function]
+ cls.add_method('HasNext',
+ 'bool',
+ [],
+ is_const=True)
+ ## packet.h: ns3::ByteTagIterator::Item ns3::ByteTagIterator::Next() [member function]
+ cls.add_method('Next',
+ 'ns3::ByteTagIterator::Item',
+ [])
+ return
+
+def register_Ns3ByteTagIteratorItem_methods(root_module, cls):
+ ## packet.h: ns3::ByteTagIterator::Item::Item(ns3::ByteTagIterator::Item const & arg0) [copy constructor]
+ cls.add_constructor([param('ns3::ByteTagIterator::Item const &', 'arg0')])
+ ## packet.h: ns3::TypeId ns3::ByteTagIterator::Item::GetTypeId() const [member function]
+ cls.add_method('GetTypeId',
+ 'ns3::TypeId',
+ [],
+ is_const=True)
+ ## packet.h: uint32_t ns3::ByteTagIterator::Item::GetStart() const [member function]
+ cls.add_method('GetStart',
+ 'uint32_t',
+ [],
+ is_const=True)
+ ## packet.h: uint32_t ns3::ByteTagIterator::Item::GetEnd() const [member function]
+ cls.add_method('GetEnd',
+ 'uint32_t',
+ [],
+ is_const=True)
+ ## packet.h: void ns3::ByteTagIterator::Item::GetTag(ns3::Tag & tag) const [member function]
+ cls.add_method('GetTag',
+ 'void',
+ [param('ns3::Tag &', 'tag')],
+ is_const=True)
+ return
+
+def register_Ns3ByteTagList_methods(root_module, cls):
+ ## byte-tag-list.h: ns3::ByteTagList::ByteTagList() [constructor]
+ cls.add_constructor([])
+ ## byte-tag-list.h: ns3::ByteTagList::ByteTagList(ns3::ByteTagList const & o) [copy constructor]
+ cls.add_constructor([param('ns3::ByteTagList const &', 'o')])
+ ## byte-tag-list.h: ns3::TagBuffer ns3::ByteTagList::Add(ns3::TypeId tid, uint32_t bufferSize, int32_t start, int32_t end) [member function]
+ cls.add_method('Add',
+ 'ns3::TagBuffer',
+ [param('ns3::TypeId', 'tid'), param('uint32_t', 'bufferSize'), param('int32_t', 'start'), param('int32_t', 'end')])
+ ## byte-tag-list.h: void ns3::ByteTagList::Add(ns3::ByteTagList const & o) [member function]
+ cls.add_method('Add',
+ 'void',
+ [param('ns3::ByteTagList const &', 'o')])
+ ## byte-tag-list.h: void ns3::ByteTagList::RemoveAll() [member function]
+ cls.add_method('RemoveAll',
+ 'void',
+ [])
+ ## byte-tag-list.h: ns3::ByteTagList::Iterator ns3::ByteTagList::Begin(int32_t offsetStart, int32_t offsetEnd) const [member function]
+ cls.add_method('Begin',
+ 'ns3::ByteTagList::Iterator',
+ [param('int32_t', 'offsetStart'), param('int32_t', 'offsetEnd')],
+ is_const=True)
+ ## byte-tag-list.h: void ns3::ByteTagList::AddAtEnd(int32_t adjustment, int32_t appendOffset) [member function]
+ cls.add_method('AddAtEnd',
+ 'void',
+ [param('int32_t', 'adjustment'), param('int32_t', 'appendOffset')])
+ ## byte-tag-list.h: void ns3::ByteTagList::AddAtStart(int32_t adjustment, int32_t prependOffset) [member function]
+ cls.add_method('AddAtStart',
+ 'void',
+ [param('int32_t', 'adjustment'), param('int32_t', 'prependOffset')])
+ return
+
+def register_Ns3ByteTagListIterator_methods(root_module, cls):
+ ## byte-tag-list.h: ns3::ByteTagList::Iterator::Iterator(ns3::ByteTagList::Iterator const & arg0) [copy constructor]
+ cls.add_constructor([param('ns3::ByteTagList::Iterator const &', 'arg0')])
+ ## byte-tag-list.h: bool ns3::ByteTagList::Iterator::HasNext() const [member function]
+ cls.add_method('HasNext',
+ 'bool',
+ [],
+ is_const=True)
+ ## byte-tag-list.h: ns3::ByteTagList::Iterator::Item ns3::ByteTagList::Iterator::Next() [member function]
+ cls.add_method('Next',
+ 'ns3::ByteTagList::Iterator::Item',
+ [])
+ ## byte-tag-list.h: uint32_t ns3::ByteTagList::Iterator::GetOffsetStart() const [member function]
+ cls.add_method('GetOffsetStart',
+ 'uint32_t',
+ [],
+ is_const=True)
+ return
+
+def register_Ns3ByteTagListIteratorItem_methods(root_module, cls):
+ ## byte-tag-list.h: ns3::ByteTagList::Iterator::Item::tid [variable]
+ cls.add_instance_attribute('tid', 'ns3::TypeId', is_const=False)
+ ## byte-tag-list.h: ns3::ByteTagList::Iterator::Item::size [variable]
+ cls.add_instance_attribute('size', 'uint32_t', is_const=False)
+ ## byte-tag-list.h: ns3::ByteTagList::Iterator::Item::start [variable]
+ cls.add_instance_attribute('start', 'int32_t', is_const=False)
+ ## byte-tag-list.h: ns3::ByteTagList::Iterator::Item::end [variable]
+ cls.add_instance_attribute('end', 'int32_t', is_const=False)
+ ## byte-tag-list.h: ns3::ByteTagList::Iterator::Item::buf [variable]
+ cls.add_instance_attribute('buf', 'ns3::TagBuffer', is_const=False)
+ ## byte-tag-list.h: ns3::ByteTagList::Iterator::Item::Item(ns3::ByteTagList::Iterator::Item const & arg0) [copy constructor]
+ cls.add_constructor([param('ns3::ByteTagList::Iterator::Item const &', 'arg0')])
+ ## byte-tag-list.h: ns3::ByteTagList::Iterator::Item::Item(ns3::TagBuffer buf) [constructor]
+ cls.add_constructor([param('ns3::TagBuffer', 'buf')])
+ return
+
def register_Ns3DataRate_methods(root_module, cls):
cls.add_output_stream_operator()
cls.add_binary_comparison_operator('!=')
@@ -378,19 +497,24 @@
cls.add_method('AddAtEnd',
'void',
[param('ns3::Ptr< ns3::Packet const >', 'packet')])
+ ## packet.h: void ns3::Packet::AddByteTag(ns3::Tag const & tag) const [member function]
+ cls.add_method('AddByteTag',
+ 'void',
+ [param('ns3::Tag const &', 'tag')],
+ is_const=True)
## packet.h: void ns3::Packet::AddHeader(ns3::Header const & header) [member function]
cls.add_method('AddHeader',
'void',
[param('ns3::Header const &', 'header')])
+ ## packet.h: void ns3::Packet::AddPacketTag(ns3::Tag const & tag) const [member function]
+ cls.add_method('AddPacketTag',
+ 'void',
+ [param('ns3::Tag const &', 'tag')],
+ is_const=True)
## packet.h: void ns3::Packet::AddPaddingAtEnd(uint32_t size) [member function]
cls.add_method('AddPaddingAtEnd',
'void',
[param('uint32_t', 'size')])
- ## packet.h: void ns3::Packet::AddTag(ns3::Tag const & tag) const [member function]
- cls.add_method('AddTag',
- 'void',
- [param('ns3::Tag const &', 'tag')],
- is_const=True)
## packet.h: void ns3::Packet::AddTrailer(ns3::Trailer const & trailer) [member function]
cls.add_method('AddTrailer',
'void',
@@ -434,21 +558,26 @@
'void',
[],
is_static=True)
- ## packet.h: bool ns3::Packet::FindFirstMatchingTag(ns3::Tag & tag) const [member function]
- cls.add_method('FindFirstMatchingTag',
+ ## packet.h: bool ns3::Packet::FindFirstMatchingByteTag(ns3::Tag & tag) const [member function]
+ cls.add_method('FindFirstMatchingByteTag',
'bool',
[param('ns3::Tag &', 'tag')],
is_const=True)
+ ## packet.h: ns3::ByteTagIterator ns3::Packet::GetByteTagIterator() const [member function]
+ cls.add_method('GetByteTagIterator',
+ 'ns3::ByteTagIterator',
+ [],
+ is_const=True)
+ ## packet.h: ns3::PacketTagIterator ns3::Packet::GetPacketTagIterator() const [member function]
+ cls.add_method('GetPacketTagIterator',
+ 'ns3::PacketTagIterator',
+ [],
+ is_const=True)
## packet.h: uint32_t ns3::Packet::GetSize() const [member function]
cls.add_method('GetSize',
'uint32_t',
[],
is_const=True)
- ## packet.h: ns3::TagIterator ns3::Packet::GetTagIterator() const [member function]
- cls.add_method('GetTagIterator',
- 'ns3::TagIterator',
- [],
- is_const=True)
## packet.h: uint32_t ns3::Packet::GetUid() const [member function]
cls.add_method('GetUid',
'uint32_t',
@@ -464,6 +593,11 @@
'uint32_t',
[param('ns3::Header &', 'header')],
is_const=True)
+ ## packet.h: bool ns3::Packet::PeekPacketTag(ns3::Tag & tag) const [member function]
+ cls.add_method('PeekPacketTag',
+ 'bool',
+ [param('ns3::Tag &', 'tag')],
+ is_const=True)
## packet.h: uint32_t ns3::Packet::PeekTrailer(ns3::Trailer & trailer) [member function]
cls.add_method('PeekTrailer',
'uint32_t',
@@ -473,13 +607,22 @@
'void',
[param('std::ostream &', 'os')],
is_const=True)
- ## packet.h: void ns3::Packet::PrintTags(std::ostream & os) const [member function]
- cls.add_method('PrintTags',
+ ## packet.h: void ns3::Packet::PrintByteTags(std::ostream & os) const [member function]
+ cls.add_method('PrintByteTags',
'void',
[param('std::ostream &', 'os')],
is_const=True)
- ## packet.h: void ns3::Packet::RemoveAllTags() [member function]
- cls.add_method('RemoveAllTags',
+ ## packet.h: void ns3::Packet::PrintPacketTags(std::ostream & os) const [member function]
+ cls.add_method('PrintPacketTags',
+ 'void',
+ [param('std::ostream &', 'os')],
+ is_const=True)
+ ## packet.h: void ns3::Packet::RemoveAllByteTags() [member function]
+ cls.add_method('RemoveAllByteTags',
+ 'void',
+ [])
+ ## packet.h: void ns3::Packet::RemoveAllPacketTags() [member function]
+ cls.add_method('RemoveAllPacketTags',
'void',
[])
## packet.h: void ns3::Packet::RemoveAtEnd(uint32_t size) [member function]
@@ -494,6 +637,10 @@
cls.add_method('RemoveHeader',
'uint32_t',
[param('ns3::Header &', 'header')])
+ ## packet.h: bool ns3::Packet::RemovePacketTag(ns3::Tag & tag) [member function]
+ cls.add_method('RemovePacketTag',
+ 'bool',
+ [param('ns3::Tag &', 'tag')])
## packet.h: uint32_t ns3::Packet::RemoveTrailer(ns3::Trailer & trailer) [member function]
cls.add_method('RemoveTrailer',
'uint32_t',
@@ -618,6 +765,80 @@
[])
return
+def register_Ns3PacketTagIterator_methods(root_module, cls):
+ ## packet.h: ns3::PacketTagIterator::PacketTagIterator(ns3::PacketTagIterator const & arg0) [copy constructor]
+ cls.add_constructor([param('ns3::PacketTagIterator const &', 'arg0')])
+ ## packet.h: bool ns3::PacketTagIterator::HasNext() const [member function]
+ cls.add_method('HasNext',
+ 'bool',
+ [],
+ is_const=True)
+ ## packet.h: ns3::PacketTagIterator::Item ns3::PacketTagIterator::Next() [member function]
+ cls.add_method('Next',
+ 'ns3::PacketTagIterator::Item',
+ [])
+ return
+
+def register_Ns3PacketTagIteratorItem_methods(root_module, cls):
+ ## packet.h: ns3::PacketTagIterator::Item::Item(ns3::PacketTagIterator::Item const & arg0) [copy constructor]
+ cls.add_constructor([param('ns3::PacketTagIterator::Item const &', 'arg0')])
+ ## packet.h: ns3::TypeId ns3::PacketTagIterator::Item::GetTypeId() const [member function]
+ cls.add_method('GetTypeId',
+ 'ns3::TypeId',
+ [],
+ is_const=True)
+ ## packet.h: void ns3::PacketTagIterator::Item::GetTag(ns3::Tag & tag) const [member function]
+ cls.add_method('GetTag',
+ 'void',
+ [param('ns3::Tag &', 'tag')],
+ is_const=True)
+ return
+
+def register_Ns3PacketTagList_methods(root_module, cls):
+ ## packet-tag-list.h: ns3::PacketTagList::PacketTagList() [constructor]
+ cls.add_constructor([])
+ ## packet-tag-list.h: ns3::PacketTagList::PacketTagList(ns3::PacketTagList const & o) [copy constructor]
+ cls.add_constructor([param('ns3::PacketTagList const &', 'o')])
+ ## packet-tag-list.h: void ns3::PacketTagList::Add(ns3::Tag const & tag) const [member function]
+ cls.add_method('Add',
+ 'void',
+ [param('ns3::Tag const &', 'tag')],
+ is_const=True)
+ ## packet-tag-list.h: bool ns3::PacketTagList::Remove(ns3::Tag & tag) [member function]
+ cls.add_method('Remove',
+ 'bool',
+ [param('ns3::Tag &', 'tag')])
+ ## packet-tag-list.h: bool ns3::PacketTagList::Peek(ns3::Tag & tag) const [member function]
+ cls.add_method('Peek',
+ 'bool',
+ [param('ns3::Tag &', 'tag')],
+ is_const=True)
+ ## packet-tag-list.h: void ns3::PacketTagList::RemoveAll() [member function]
+ cls.add_method('RemoveAll',
+ 'void',
+ [])
+ ## packet-tag-list.h: ns3::PacketTagList::TagData const * ns3::PacketTagList::Head() const [member function]
+ cls.add_method('Head',
+ 'ns3::PacketTagList::TagData const *',
+ [],
+ is_const=True)
+ return
+
+def register_Ns3PacketTagListTagData_methods(root_module, cls):
+ ## packet-tag-list.h: ns3::PacketTagList::TagData::data [variable]
+ cls.add_instance_attribute('data', 'uint8_t [ 20 ]', is_const=False)
+ ## packet-tag-list.h: ns3::PacketTagList::TagData::next [variable]
+ cls.add_instance_attribute('next', 'ns3::PacketTagList::TagData *', is_const=False)
+ ## packet-tag-list.h: ns3::PacketTagList::TagData::tid [variable]
+ cls.add_instance_attribute('tid', 'ns3::TypeId', is_const=False)
+ ## packet-tag-list.h: ns3::PacketTagList::TagData::count [variable]
+ cls.add_instance_attribute('count', 'uint32_t', is_const=False)
+ ## packet-tag-list.h: ns3::PacketTagList::TagData::TagData(ns3::PacketTagList::TagData const & arg0) [copy constructor]
+ cls.add_constructor([param('ns3::PacketTagList::TagData const &', 'arg0')])
+ ## packet-tag-list.h: ns3::PacketTagList::TagData::TagData() [constructor]
+ cls.add_constructor([])
+ return
+
def register_Ns3Tag_methods(root_module, cls):
## tag.h: ns3::Tag::Tag(ns3::Tag const & arg0) [copy constructor]
cls.add_constructor([param('ns3::Tag const &', 'arg0')])
@@ -713,113 +934,6 @@
[param('uint8_t *', 'buffer'), param('uint32_t', 'size')])
return
-def register_Ns3TagIterator_methods(root_module, cls):
- ## packet.h: ns3::TagIterator::TagIterator(ns3::TagIterator const & arg0) [copy constructor]
- cls.add_constructor([param('ns3::TagIterator const &', 'arg0')])
- ## packet.h: bool ns3::TagIterator::HasNext() const [member function]
- cls.add_method('HasNext',
- 'bool',
- [],
- is_const=True)
- ## packet.h: ns3::TagIterator::Item ns3::TagIterator::Next() [member function]
- cls.add_method('Next',
- 'ns3::TagIterator::Item',
- [])
- return
-
-def register_Ns3TagIteratorItem_methods(root_module, cls):
- ## packet.h: ns3::TagIterator::Item::Item(ns3::TagIterator::Item const & arg0) [copy constructor]
- cls.add_constructor([param('ns3::TagIterator::Item const &', 'arg0')])
- ## packet.h: ns3::TypeId ns3::TagIterator::Item::GetTypeId() const [member function]
- cls.add_method('GetTypeId',
- 'ns3::TypeId',
- [],
- is_const=True)
- ## packet.h: uint32_t ns3::TagIterator::Item::GetStart() const [member function]
- cls.add_method('GetStart',
- 'uint32_t',
- [],
- is_const=True)
- ## packet.h: uint32_t ns3::TagIterator::Item::GetEnd() const [member function]
- cls.add_method('GetEnd',
- 'uint32_t',
- [],
- is_const=True)
- ## packet.h: void ns3::TagIterator::Item::GetTag(ns3::Tag & tag) const [member function]
- cls.add_method('GetTag',
- 'void',
- [param('ns3::Tag &', 'tag')],
- is_const=True)
- return
-
-def register_Ns3TagList_methods(root_module, cls):
- ## tag-list.h: ns3::TagList::TagList() [constructor]
- cls.add_constructor([])
- ## tag-list.h: ns3::TagList::TagList(ns3::TagList const & o) [copy constructor]
- cls.add_constructor([param('ns3::TagList const &', 'o')])
- ## tag-list.h: ns3::TagBuffer ns3::TagList::Add(ns3::TypeId tid, uint32_t bufferSize, int32_t start, int32_t end) [member function]
- cls.add_method('Add',
- 'ns3::TagBuffer',
- [param('ns3::TypeId', 'tid'), param('uint32_t', 'bufferSize'), param('int32_t', 'start'), param('int32_t', 'end')])
- ## tag-list.h: void ns3::TagList::Add(ns3::TagList const & o) [member function]
- cls.add_method('Add',
- 'void',
- [param('ns3::TagList const &', 'o')])
- ## tag-list.h: void ns3::TagList::RemoveAll() [member function]
- cls.add_method('RemoveAll',
- 'void',
- [])
- ## tag-list.h: ns3::TagList::Iterator ns3::TagList::Begin(int32_t offsetStart, int32_t offsetEnd) const [member function]
- cls.add_method('Begin',
- 'ns3::TagList::Iterator',
- [param('int32_t', 'offsetStart'), param('int32_t', 'offsetEnd')],
- is_const=True)
- ## tag-list.h: void ns3::TagList::AddAtEnd(int32_t adjustment, int32_t appendOffset) [member function]
- cls.add_method('AddAtEnd',
- 'void',
- [param('int32_t', 'adjustment'), param('int32_t', 'appendOffset')])
- ## tag-list.h: void ns3::TagList::AddAtStart(int32_t adjustment, int32_t prependOffset) [member function]
- cls.add_method('AddAtStart',
- 'void',
- [param('int32_t', 'adjustment'), param('int32_t', 'prependOffset')])
- return
-
-def register_Ns3TagListIterator_methods(root_module, cls):
- ## tag-list.h: ns3::TagList::Iterator::Iterator(ns3::TagList::Iterator const & arg0) [copy constructor]
- cls.add_constructor([param('ns3::TagList::Iterator const &', 'arg0')])
- ## tag-list.h: bool ns3::TagList::Iterator::HasNext() const [member function]
- cls.add_method('HasNext',
- 'bool',
- [],
- is_const=True)
- ## tag-list.h: ns3::TagList::Iterator::Item ns3::TagList::Iterator::Next() [member function]
- cls.add_method('Next',
- 'ns3::TagList::Iterator::Item',
- [])
- ## tag-list.h: uint32_t ns3::TagList::Iterator::GetOffsetStart() const [member function]
- cls.add_method('GetOffsetStart',
- 'uint32_t',
- [],
- is_const=True)
- return
-
-def register_Ns3TagListIteratorItem_methods(root_module, cls):
- ## tag-list.h: ns3::TagList::Iterator::Item::tid [variable]
- cls.add_instance_attribute('tid', 'ns3::TypeId', is_const=False)
- ## tag-list.h: ns3::TagList::Iterator::Item::size [variable]
- cls.add_instance_attribute('size', 'uint32_t', is_const=False)
- ## tag-list.h: ns3::TagList::Iterator::Item::start [variable]
- cls.add_instance_attribute('start', 'int32_t', is_const=False)
- ## tag-list.h: ns3::TagList::Iterator::Item::end [variable]
- cls.add_instance_attribute('end', 'int32_t', is_const=False)
- ## tag-list.h: ns3::TagList::Iterator::Item::buf [variable]
- cls.add_instance_attribute('buf', 'ns3::TagBuffer', is_const=False)
- ## tag-list.h: ns3::TagList::Iterator::Item::Item(ns3::TagList::Iterator::Item const & arg0) [copy constructor]
- cls.add_constructor([param('ns3::TagList::Iterator::Item const &', 'arg0')])
- ## tag-list.h: ns3::TagList::Iterator::Item::Item(ns3::TagBuffer buf) [constructor]
- cls.add_constructor([param('ns3::TagBuffer', 'buf')])
- return
-
def register_Ns3Chunk_methods(root_module, cls):
## chunk.h: ns3::Chunk::Chunk(ns3::Chunk const & arg0) [copy constructor]
cls.add_constructor([param('ns3::Chunk const &', 'arg0')])
--- a/doc/doxygen.conf Tue Apr 21 12:32:55 2009 +0200
+++ b/doc/doxygen.conf Tue Apr 21 16:22:45 2009 +0400
@@ -300,7 +300,7 @@
# If set to NO (the default) these classes will be included in the various
# overviews. This option has no effect if EXTRACT_ALL is enabled.
-HIDE_UNDOC_CLASSES = YES
+HIDE_UNDOC_CLASSES = NO
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
# friend (class|struct|union) declarations.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/mesh.cc Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,132 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#include "ns3/core-module.h"
+#include "ns3/simulator-module.h"
+#include "ns3/node-module.h"
+#include "ns3/helper-module.h"
+#include "ns3/global-routing-module.h"
+#include "ns3/wifi-module.h"
+#include "ns3/mesh-module.h"
+#include "ns3/mobility-module.h"
+
+#include "ns3/dot11s-helper.h"
+
+using namespace ns3;
+using namespace dot11s;
+
+NS_LOG_COMPONENT_DEFINE ("TestMeshScript");
+
+int
+main (int argc, char *argv[])
+{
+ // Creating square topology with xSize x ySize grid
+ int xSize = 3;
+ int ySize = 3;
+ double step = 100.0;
+ double randomStart = 0.1;
+ double totalTime = 100.0;
+ double packetInterval = 0.001;
+ uint16_t packetSize = 1024;
+ uint32_t nIfaces = 1;
+ bool chan = true;
+ bool pcap = false;
+ uint64_t seed = 1;
+
+ // Command line arguments
+ CommandLine cmd;
+ cmd.AddValue ("x-size", "Number of nodes in a row grid. [6]", xSize);
+ cmd.AddValue ("y-size", "Number of rows in a grid. [6]", ySize);
+ cmd.AddValue ("step", "Size of edge in our grid, meters. [100 m]", step);
+ cmd.AddValue ("start", "Maximum random start delay, seconds. [0.1 s]", randomStart);
+ cmd.AddValue ("time", "Simulation time, seconds [100 s]", totalTime);
+ cmd.AddValue ("packet-interval", "Interval between packets, seconds [0.001 s]", packetInterval);
+ cmd.AddValue ("packet-size", "Size of packets", packetSize);
+ cmd.AddValue ("interfaces", "Number of radio interfaces used by each mesh point. [1]", nIfaces);
+ cmd.AddValue ("channels", "Use different frequency channels for different interfaces. [0]", chan);
+ cmd.AddValue ("pcap", "Enable PCAP traces on interfaces. [0]", pcap);
+ cmd.AddValue ("seed", "Seed value", seed);
+
+ cmd.Parse (argc, argv);
+ NS_LOG_DEBUG ("Grid:" << xSize << "*" << ySize);
+ NS_LOG_DEBUG ("Simulation time: " << totalTime << " s");
+ SeedManager::SetSeed(seed);
+ // Creating nodes
+ NodeContainer nodes;
+ nodes.Create (ySize*xSize);
+
+ // Setting channel
+ YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default ();
+ YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default ();
+ wifiPhy.SetChannel (wifiChannel.Create ());
+
+ // Install mesh point devices & protocols
+ MeshWifiHelper mesh;
+ mesh.SetSpreadInterfaceChannels (chan);
+ std::vector<uint32_t> roots;
+ //roots.push_back(xSize-1);
+ //roots.push_back(xSize*ySize-xSize);
+ NetDeviceContainer meshDevices = mesh.Install (wifiPhy, nodes, roots, nIfaces);
+
+ // Setup mobility
+ MobilityHelper mobility;
+ mobility.SetPositionAllocator ("ns3::GridPositionAllocator",
+ "MinX", DoubleValue (0.0),
+ "MinY", DoubleValue (0.0),
+ "DeltaX", DoubleValue (step),
+ "DeltaY", DoubleValue (step),
+ "GridWidth", UintegerValue (xSize),
+ "LayoutType", StringValue ("RowFirst"));
+ mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+ mobility.Install (nodes);
+
+ NS_LOG_UNCOND("start");
+
+ // Install internet stack
+ InternetStackHelper stack;
+ stack.Install (nodes);
+ Ipv4AddressHelper address;
+ address.SetBase ("10.1.1.0", "255.255.255.0");
+ Ipv4InterfaceContainer interfaces = address.Assign (meshDevices);
+
+ // Install applications
+ UdpEchoServerHelper echoServer (9);
+ ApplicationContainer serverApps = echoServer.Install (nodes.Get (0));
+ serverApps.Start (Seconds (0.0));
+ serverApps.Stop (Seconds (totalTime));
+ UdpEchoClientHelper echoClient (interfaces.GetAddress (0), 9);
+ echoClient.SetAttribute ("MaxPackets", UintegerValue ((uint32_t)(totalTime*(1/packetInterval))));
+ echoClient.SetAttribute ("Interval", TimeValue (Seconds (packetInterval)));
+ echoClient.SetAttribute ("PacketSize", UintegerValue (packetSize));
+ ApplicationContainer clientApps = echoClient.Install (nodes.Get (xSize*ySize-1));
+ clientApps.Start (Seconds (0.0));
+ clientApps.Stop (Seconds (totalTime));
+
+ // Enable PCAP trace
+ if (pcap)
+ wifiPhy.EnablePcapAll (std::string ("mp-") + mesh.GetSsid ().PeekString ());
+
+ // Happy end
+ Simulator::Stop (Seconds (totalTime));
+ Simulator::Run ();
+ Simulator::Destroy ();
+ return 0;
+}
--- a/examples/stats/wifi-example-apps.cc Tue Apr 21 12:32:55 2009 +0200
+++ b/examples/stats/wifi-example-apps.cc Tue Apr 21 16:22:45 2009 +0400
@@ -131,7 +131,7 @@
TimestampTag timestamp;
timestamp.SetTimestamp(Simulator::Now());
- packet->AddTag(timestamp);
+ packet->AddByteTag (timestamp);
// Could connect the socket since the address never changes; using SendTo
// here simply because all of the standard apps do not.
@@ -250,7 +250,7 @@
}
TimestampTag timestamp;
- packet->FindFirstMatchingTag(timestamp);
+ packet->FindFirstMatchingByteTag(timestamp);
Time tx = timestamp.GetTimestamp();
if (m_delay != 0) {
--- a/examples/wscript Tue Apr 21 12:32:55 2009 +0200
+++ b/examples/wscript Tue Apr 21 16:22:45 2009 +0400
@@ -120,6 +120,10 @@
['core', 'simulator', 'mobility', 'wifi'])
obj.source = 'wifi-ap.cc'
+ obj = bld.create_ns3_program('mesh',
+ ['core', 'simulator', 'mobility', 'wifi'])
+ obj.source = 'mesh.cc'
+
bld.add_subdirs('stats')
obj = bld.create_ns3_program('wifi-wired-bridging',
--- a/samples/main-packet-tag.cc Tue Apr 21 12:32:55 2009 +0200
+++ b/samples/main-packet-tag.cc Tue Apr 21 16:22:45 2009 +0400
@@ -101,19 +101,19 @@
// store the tag in a packet.
Ptr<Packet> p = Create<Packet> (100);
- p->AddTag (tag);
+ p->AddPacketTag (tag);
// create a copy of the packet
Ptr<Packet> aCopy = p->Copy ();
// read the tag from the packet copy
MyTag tagCopy;
- p->FindFirstMatchingTag (tagCopy);
+ p->PeekPacketTag (tagCopy);
// the copy and the original are the same !
NS_ASSERT (tagCopy.GetSimpleValue () == tag.GetSimpleValue ());
- aCopy->PrintTags (std::cout);
+ aCopy->PrintPacketTags (std::cout);
std::cout << std::endl;
return 0;
--- a/src/applications/udp-echo/udp-echo-server.cc Tue Apr 21 12:32:55 2009 +0200
+++ b/src/applications/udp-echo/udp-echo-server.cc Tue Apr 21 16:22:45 2009 +0400
@@ -104,7 +104,7 @@
NS_LOG_INFO ("Received " << packet->GetSize() << " bytes from " <<
address.GetIpv4());
- packet->RemoveAllTags ();
+ packet->RemoveAllPacketTags ();
NS_LOG_LOGIC ("Echoing packet");
socket->SendTo (packet, 0, from);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/byte-tag-list.cc Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,421 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "byte-tag-list.h"
+#include "ns3/log.h"
+#include <vector>
+#include <string.h>
+
+NS_LOG_COMPONENT_DEFINE ("ByteTagList");
+
+#define USE_FREE_LIST 1
+#define FREE_LIST_SIZE 1000
+#define OFFSET_MAX (2147483647)
+
+namespace ns3 {
+
+struct ByteTagListData {
+ uint32_t size;
+ uint32_t count;
+ uint32_t dirty;
+ uint8_t data[4];
+};
+
+#ifdef USE_FREE_LIST
+static class ByteTagListDataFreeList : public std::vector<struct ByteTagListData *>
+{
+public:
+ ~ByteTagListDataFreeList ();
+} g_freeList;
+static uint32_t g_maxSize = 0;
+
+ByteTagListDataFreeList::~ByteTagListDataFreeList ()
+{
+ for (ByteTagListDataFreeList::iterator i = begin ();
+ i != end (); i++)
+ {
+ uint8_t *buffer = (uint8_t *)(*i);
+ delete [] buffer;
+ }
+}
+#endif /* USE_FREE_LIST */
+
+ByteTagList::Iterator::Item::Item (TagBuffer buf_)
+ : buf (buf_)
+{}
+
+bool
+ByteTagList::Iterator::HasNext (void) const
+{
+ return m_current < m_end;
+}
+struct ByteTagList::Iterator::Item
+ByteTagList::Iterator::Next (void)
+{
+ NS_ASSERT (HasNext ());
+ struct Item item = Item (TagBuffer (m_current+16, m_end));
+ item.tid.SetUid (m_nextTid);
+ item.size = m_nextSize;
+ item.start = std::max (m_nextStart, m_offsetStart);
+ item.end = std::min (m_nextEnd, m_offsetEnd);
+ m_current += 4 + 4 + 4 + 4 + item.size;
+ item.buf.TrimAtEnd (m_end - m_current);
+ PrepareForNext ();
+ return item;
+}
+void
+ByteTagList::Iterator::PrepareForNext (void)
+{
+ while (m_current < m_end)
+ {
+ TagBuffer buf = TagBuffer (m_current, m_end);
+ m_nextTid = buf.ReadU32 ();
+ m_nextSize = buf.ReadU32 ();
+ m_nextStart = buf.ReadU32 ();
+ m_nextEnd = buf.ReadU32 ();
+ if (m_nextStart >= m_offsetEnd || m_nextEnd <= m_offsetStart)
+ {
+ m_current += 4 + 4 + 4 + 4 + m_nextSize;
+ }
+ else
+ {
+ break;
+ }
+ }
+}
+ByteTagList::Iterator::Iterator (uint8_t *start, uint8_t *end, int32_t offsetStart, int32_t offsetEnd)
+ : m_current (start),
+ m_end (end),
+ m_offsetStart (offsetStart),
+ m_offsetEnd (offsetEnd)
+{
+ PrepareForNext ();
+}
+
+uint32_t
+ByteTagList::Iterator::GetOffsetStart (void) const
+{
+ return m_offsetStart;
+}
+
+
+ByteTagList::ByteTagList ()
+ : m_used (0),
+ m_data (0)
+{
+ NS_LOG_FUNCTION (this);
+}
+ByteTagList::ByteTagList (const ByteTagList &o)
+ : m_used (o.m_used),
+ m_data (o.m_data)
+{
+ NS_LOG_FUNCTION (this << &o);
+ if (m_data != 0)
+ {
+ m_data->count++;
+ }
+}
+ByteTagList &
+ByteTagList::operator = (const ByteTagList &o)
+{
+ NS_LOG_FUNCTION (this << &o);
+ if (this == &o)
+ {
+ return *this;
+ }
+
+ Deallocate (m_data);
+ m_data = o.m_data;
+ m_used = o.m_used;
+ if (m_data != 0)
+ {
+ m_data->count++;
+ }
+ return *this;
+}
+ByteTagList::~ByteTagList ()
+{
+ NS_LOG_FUNCTION (this);
+ Deallocate (m_data);
+ m_data = 0;
+ m_used = 0;
+}
+
+TagBuffer
+ByteTagList::Add (TypeId tid, uint32_t bufferSize, int32_t start, int32_t end)
+{
+ NS_LOG_FUNCTION (this << tid << bufferSize << start << end);
+ uint32_t spaceNeeded = m_used + bufferSize + 4 + 4 + 4 + 4;
+ NS_ASSERT (m_used <= spaceNeeded);
+ if (m_data == 0)
+ {
+ m_data = Allocate (spaceNeeded);
+ m_used = 0;
+ }
+ else if (m_data->size < spaceNeeded ||
+ (m_data->count != 1 && m_data->dirty != m_used))
+ {
+ struct ByteTagListData *newData = Allocate (spaceNeeded);
+ memcpy (&newData->data, &m_data->data, m_used);
+ Deallocate (m_data);
+ m_data = newData;
+ }
+ TagBuffer tag = TagBuffer (&m_data->data[m_used],
+ &m_data->data[spaceNeeded]);
+ tag.WriteU32 (tid.GetUid ());
+ tag.WriteU32 (bufferSize);
+ tag.WriteU32 (start);
+ tag.WriteU32 (end);
+ m_used = spaceNeeded;
+ m_data->dirty = m_used;
+ return tag;
+}
+
+void
+ByteTagList::Add (const ByteTagList &o)
+{
+ NS_LOG_FUNCTION (this << &o);
+ ByteTagList::Iterator i = o.BeginAll ();
+ while (i.HasNext ())
+ {
+ ByteTagList::Iterator::Item item = i.Next ();
+ TagBuffer buf = Add (item.tid, item.size, item.start, item.end);
+ buf.CopyFrom (item.buf);
+ }
+}
+
+void
+ByteTagList::RemoveAll (void)
+{
+ NS_LOG_FUNCTION (this);
+ Deallocate (m_data);
+ m_data = 0;
+ m_used = 0;
+}
+
+ByteTagList::Iterator
+ByteTagList::BeginAll (void) const
+{
+ NS_LOG_FUNCTION (this);
+ // I am not totally sure but I might need to use
+ // INT32_MIN instead of zero below.
+ return Begin (0, OFFSET_MAX);
+}
+
+ByteTagList::Iterator
+ByteTagList::Begin (int32_t offsetStart, int32_t offsetEnd) const
+{
+ NS_LOG_FUNCTION (this << offsetStart << offsetEnd);
+ if (m_data == 0)
+ {
+ return Iterator (0, 0, offsetStart, offsetEnd);
+ }
+ else
+ {
+ return Iterator (m_data->data, &m_data->data[m_used], offsetStart, offsetEnd);
+ }
+}
+
+bool
+ByteTagList::IsDirtyAtEnd (int32_t appendOffset)
+{
+ NS_LOG_FUNCTION (this << appendOffset);
+ ByteTagList::Iterator i = BeginAll ();
+ while (i.HasNext ())
+ {
+ ByteTagList::Iterator::Item item = i.Next ();
+ if (item.end > appendOffset)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool
+ByteTagList::IsDirtyAtStart (int32_t prependOffset)
+{
+ NS_LOG_FUNCTION (this << prependOffset);
+ ByteTagList::Iterator i = BeginAll ();
+ while (i.HasNext ())
+ {
+ ByteTagList::Iterator::Item item = i.Next ();
+ if (item.start < prependOffset)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+void
+ByteTagList::AddAtEnd (int32_t adjustment, int32_t appendOffset)
+{
+ NS_LOG_FUNCTION (this << adjustment << appendOffset);
+ if (adjustment == 0 && !IsDirtyAtEnd (appendOffset))
+ {
+ return;
+ }
+ ByteTagList list;
+ ByteTagList::Iterator i = BeginAll ();
+ while (i.HasNext ())
+ {
+ ByteTagList::Iterator::Item item = i.Next ();
+ item.start += adjustment;
+ item.end += adjustment;
+
+ if (item.start >= appendOffset)
+ {
+ continue;
+ }
+ else if (item.start < appendOffset && item.end > appendOffset)
+ {
+ item.end = appendOffset;
+ }
+ else
+ {
+ // nothing to do.
+ }
+ TagBuffer buf = list.Add (item.tid, item.size, item.start, item.end);
+ buf.CopyFrom (item.buf);
+ }
+ *this = list;
+}
+
+void
+ByteTagList::AddAtStart (int32_t adjustment, int32_t prependOffset)
+{
+ NS_LOG_FUNCTION (this << adjustment << prependOffset);
+ if (adjustment == 0 && !IsDirtyAtStart (prependOffset))
+ {
+ return;
+ }
+ ByteTagList list;
+ ByteTagList::Iterator i = BeginAll ();
+ while (i.HasNext ())
+ {
+ ByteTagList::Iterator::Item item = i.Next ();
+ item.start += adjustment;
+ item.end += adjustment;
+
+ if (item.end <= prependOffset)
+ {
+ continue;
+ }
+ else if (item.end > prependOffset && item.start < prependOffset)
+ {
+ item.start = prependOffset;
+ }
+ else
+ {
+ // nothing to do.
+ }
+ TagBuffer buf = list.Add (item.tid, item.size, item.start, item.end);
+ buf.CopyFrom (item.buf);
+ }
+ *this = list;
+}
+
+#ifdef USE_FREE_LIST
+
+struct ByteTagListData *
+ByteTagList::Allocate (uint32_t size)
+{
+ NS_LOG_FUNCTION (this << size);
+ while (!g_freeList.empty ())
+ {
+ struct ByteTagListData *data = g_freeList.back ();
+ g_freeList.pop_back ();
+ NS_ASSERT (data != 0);
+ if (data->size >= size)
+ {
+ data->count = 1;
+ data->dirty = 0;
+ return data;
+ }
+ uint8_t *buffer = (uint8_t *)data;
+ delete [] buffer;
+ }
+ uint8_t *buffer = new uint8_t [std::max (size, g_maxSize) + sizeof (struct ByteTagListData) - 4];
+ struct ByteTagListData *data = (struct ByteTagListData *)buffer;
+ data->count = 1;
+ data->size = size;
+ data->dirty = 0;
+ return data;
+}
+
+void
+ByteTagList::Deallocate (struct ByteTagListData *data)
+{
+ NS_LOG_FUNCTION (this << data);
+ if (data == 0)
+ {
+ return;
+ }
+ g_maxSize = std::max (g_maxSize, data->size);
+ data->count--;
+ if (data->count == 0)
+ {
+ if (g_freeList.size () > FREE_LIST_SIZE ||
+ data->size < g_maxSize)
+ {
+ uint8_t *buffer = (uint8_t *)data;
+ delete [] buffer;
+ }
+ else
+ {
+ g_freeList.push_back (data);
+ }
+ }
+}
+
+#else /* USE_FREE_LIST */
+
+struct ByteTagListData *
+ByteTagList::Allocate (uint32_t size)
+{
+ NS_LOG_FUNCTION (this << size);
+ uint8_t *buffer = new uint8_t [size + sizeof (struct ByteTagListData) - 4];
+ struct ByteTagListData *data = (struct ByteTagListData *)buffer;
+ data->count = 1;
+ data->size = size;
+ data->dirty = 0;
+ return data;
+}
+
+void
+ByteTagList::Deallocate (struct ByteTagListData *data)
+{
+ NS_LOG_FUNCTION (this << data);
+ if (data == 0)
+ {
+ return;
+ }
+ data->count--;
+ if (data->count == 0)
+ {
+ uint8_t *buffer = (uint8_t *)data;
+ delete [] buffer;
+ }
+}
+
+#endif /* USE_FREE_LIST */
+
+
+} // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/byte-tag-list.h Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,170 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef BYTE_TAG_LIST_H
+#define BYTE_TAG_LIST_H
+
+#include <stdint.h>
+#include "ns3/type-id.h"
+#include "tag-buffer.h"
+
+namespace ns3 {
+
+struct ByteTagListData;
+
+/**
+ * \ingroup packet
+ *
+ * \brief keep track of the tags stored in a packet.
+ *
+ * This class is mostly private to the Packet implementation and users
+ * should never have to access it directly.
+ *
+ * \internal
+ * The implementation of this class is a bit tricky so, there are a couple
+ * of things to keep in mind here:
+ *
+ * - it stores all tags in a single byte buffer: each tag is stored
+ * as 4 32bit integers (TypeId, tag data size, start, end) followed
+ * by the tag data as generated by Tag::Serialize.
+ *
+ * - the struct ByteTagListData structure which contains the tag byte buffer
+ * is shared and, thus, reference-counted. This data structure is unshared
+ * as-needed to emulate COW semantics.
+ *
+ * - each tag tags a unique set of bytes identified by the pair of offsets
+ * (start,end). These offsets are provided by Buffer::GetCurrentStartOffset
+ * and Buffer::GetCurrentEndOffset which means that they are relative to
+ * the start of the 'virtual byte buffer' as explained in the documentation
+ * for the ns3::Buffer class. Whenever the origin of the offset of the Buffer
+ * instance associated to this ByteTagList instance changes, the Buffer class
+ * reports this to its container Packet class as a bool return value
+ * in Buffer::AddAtStart and Buffer::AddAtEnd. In both cases, when this happens
+ * the Packet class calls ByteTagList::AddAtEnd and ByteTagList::AddAtStart to update
+ * the byte offsets of each tag in the ByteTagList.
+ *
+ * - whenever bytes are removed from the packet byte buffer, the ByteTagList offsets
+ * are never updated because we rely on the fact that they will be updated in
+ * either the next call to Packet::AddHeader or Packet::AddTrailer or when
+ * the user iterates the tag list with Packet::GetTagIterator and
+ * TagIterator::Next.
+ */
+class ByteTagList
+{
+public:
+
+ class Iterator
+ {
+ public:
+ struct Item
+ {
+ TypeId tid;
+ uint32_t size;
+ int32_t start;
+ int32_t end;
+ TagBuffer buf;
+ Item (TagBuffer buf);
+ private:
+ friend class ByteTagList;
+ friend class ByteTagList::Iterator;
+ };
+ bool HasNext (void) const;
+ struct ByteTagList::Iterator::Item Next (void);
+ uint32_t GetOffsetStart (void) const;
+ private:
+ friend class ByteTagList;
+ Iterator (uint8_t *start, uint8_t *end, int32_t offsetStart, int32_t offsetEnd);
+ void PrepareForNext (void);
+ uint8_t *m_current;
+ uint8_t *m_end;
+ int32_t m_offsetStart;
+ int32_t m_offsetEnd;
+ uint32_t m_nextTid;
+ uint32_t m_nextSize;
+ int32_t m_nextStart;
+ int32_t m_nextEnd;
+ };
+
+ ByteTagList ();
+ ByteTagList (const ByteTagList &o);
+ ByteTagList &operator = (const ByteTagList &o);
+ ~ByteTagList ();
+
+ /**
+ * \param tid the typeid of the tag added
+ * \param bufferSize the size of the tag when its serialization will
+ * be completed. Typically, the return value of Tag::GetSerializedSize
+ * \param start offset which uniquely identifies the first byte tagged by this tag.
+ * \param end offset which uniquely identifies the last byte tagged by this tag.
+ * \returns a buffer which can be used to write the tag data.
+ *
+ *
+ */
+ TagBuffer Add (TypeId tid, uint32_t bufferSize, int32_t start, int32_t end);
+
+ /**
+ * \param o the other list of tags to aggregate.
+ *
+ * Aggregate the two lists of tags.
+ */
+ void Add (const ByteTagList &o);
+
+ void RemoveAll (void);
+
+ /**
+ * \param offsetStart the offset which uniquely identifies the first data byte
+ * present in the byte buffer associated to this ByteTagList.
+ * \param offsetEnd the offset which uniquely identifies the last data byte
+ * present in the byte buffer associated to this ByteTagList.
+ * \returns an iterator
+ *
+ * The returned iterator will allow you to loop through the set of tags present
+ * in this list: the boundaries of each tag as reported by their start and
+ * end offsets will be included within the input offsetStart and offsetEnd.
+ */
+ ByteTagList::Iterator Begin (int32_t offsetStart, int32_t offsetEnd) const;
+
+ /**
+ * Adjust the offsets stored internally by the adjustment delta and
+ * make sure that all offsets are smaller than appendOffset which represents
+ * the location where new bytes have been added to the byte buffer.
+ */
+ void AddAtEnd (int32_t adjustment, int32_t appendOffset);
+ /**
+ * Adjust the offsets stored internally by the adjustment delta and
+ * make sure that all offsets are bigger than prependOffset which represents
+ * the location where new bytes have been added to the byte buffer.
+ */
+ void AddAtStart (int32_t adjustment, int32_t prependOffset);
+
+private:
+ bool IsDirtyAtEnd (int32_t appendOffset);
+ bool IsDirtyAtStart (int32_t prependOffset);
+ ByteTagList::Iterator BeginAll (void) const;
+
+ struct ByteTagListData *Allocate (uint32_t size);
+ void Deallocate (struct ByteTagListData *data);
+
+ uint16_t m_used;
+ struct ByteTagListData *m_data;
+};
+
+} // namespace ns3
+
+#endif /* BYTE_TAG_LIST_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/packet-tag-list.cc Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,177 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "packet-tag-list.h"
+#include "tag-buffer.h"
+#include "tag.h"
+#include "ns3/fatal-error.h"
+#include "ns3/log.h"
+#include <string.h>
+
+NS_LOG_COMPONENT_DEFINE ("PacketTagList");
+
+namespace ns3 {
+
+#ifdef USE_FREE_LIST
+
+struct PacketTagList::TagData *PacketTagList::g_free = 0;
+uint32_t PacketTagList::g_nfree = 0;
+
+struct PacketTagList::TagData *
+PacketTagList::AllocData (void) const
+{
+ NS_LOG_FUNCTION (g_nfree);
+ struct PacketTagList::TagData *retval;
+ if (g_free != 0)
+ {
+ retval = g_free;
+ g_free = g_free->m_next;
+ g_nfree--;
+ }
+ else
+ {
+ retval = new struct PacketTagList::TagData ();
+ }
+ return retval;
+}
+
+void
+PacketTagList::FreeData (struct TagData *data) const
+{
+ NS_LOG_FUNCTION (g_nfree << data);
+ if (g_nfree > 1000)
+ {
+ delete data;
+ return;
+ }
+ g_nfree++;
+ data->next = g_free;
+ data->tid = TypeId ();
+ g_free = data;
+}
+#else
+struct PacketTagList::TagData *
+PacketTagList::AllocData (void) const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ struct PacketTagList::TagData *retval;
+ retval = new struct PacketTagList::TagData ();
+ return retval;
+}
+
+void
+PacketTagList::FreeData (struct TagData *data) const
+{
+ NS_LOG_FUNCTION (data);
+ delete data;
+}
+#endif
+
+bool
+PacketTagList::Remove (Tag &tag)
+{
+ NS_LOG_FUNCTION (this << tag.GetInstanceTypeId ());
+ TypeId tid = tag.GetInstanceTypeId ();
+ bool found = false;
+ for (struct TagData *cur = m_next; cur != 0; cur = cur->next)
+ {
+ if (cur->tid == tid)
+ {
+ found = true;
+ tag.Deserialize (TagBuffer (cur->data, cur->data+PACKET_TAG_MAX_SIZE));
+ }
+ }
+ if (!found)
+ {
+ return false;
+ }
+ struct TagData *start = 0;
+ struct TagData **prevNext = &start;
+ for (struct TagData *cur = m_next; cur != 0; cur = cur->next)
+ {
+ if (cur->tid == tid)
+ {
+ /**
+ * XXX
+ * Note: I believe that we could optimize this to
+ * avoid copying each TagData located after the target id
+ * and just link the already-copied list to the next tag.
+ */
+ continue;
+ }
+ struct TagData *copy = AllocData ();
+ copy->tid = cur->tid;
+ copy->count = 1;
+ copy->next = 0;
+ memcpy (copy->data, cur->data, PACKET_TAG_MAX_SIZE);
+ *prevNext = copy;
+ prevNext = ©->next;
+ }
+ *prevNext = 0;
+ RemoveAll ();
+ m_next = start;
+ return true;
+}
+
+void
+PacketTagList::Add (const Tag &tag) const
+{
+ NS_LOG_FUNCTION (this << tag.GetInstanceTypeId ());
+ // ensure this id was not yet added
+ for (struct TagData *cur = m_next; cur != 0; cur = cur->next)
+ {
+ NS_ASSERT (cur->tid != tag.GetInstanceTypeId ());
+ }
+ struct TagData *head = AllocData ();
+ head->count = 1;
+ head->next = 0;
+ head->tid = tag.GetInstanceTypeId ();
+ head->next = m_next;
+ NS_ASSERT (tag.GetSerializedSize () < PACKET_TAG_MAX_SIZE);
+ tag.Serialize (TagBuffer (head->data, head->data+tag.GetSerializedSize ()));
+
+ const_cast<PacketTagList *> (this)->m_next = head;
+}
+
+bool
+PacketTagList::Peek (Tag &tag) const
+{
+ NS_LOG_FUNCTION (this << tag.GetInstanceTypeId ());
+ TypeId tid = tag.GetInstanceTypeId ();
+ for (struct TagData *cur = m_next; cur != 0; cur = cur->next)
+ {
+ if (cur->tid == tid)
+ {
+ /* found tag */
+ tag.Deserialize (TagBuffer (cur->data, cur->data+PACKET_TAG_MAX_SIZE));
+ return true;
+ }
+ }
+ /* no tag found */
+ return false;
+}
+
+const struct PacketTagList::TagData *
+PacketTagList::Head (void) const
+{
+ return m_next;
+}
+
+} // namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/packet-tag-list.h Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,142 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2006 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef PACKET_TAG_LIST_H
+#define PACKET_TAG_LIST_H
+
+#include <stdint.h>
+#include <ostream>
+#include "ns3/type-id.h"
+
+namespace ns3 {
+
+class Tag;
+
+/**
+ * \ingroup constants
+ * \brief Tag maximum size
+ * The maximum size (in bytes) of a Tag is stored
+ * in this constant.
+ */
+#define PACKET_TAG_MAX_SIZE 20
+
+class PacketTagList
+{
+public:
+ struct TagData {
+ uint8_t data[PACKET_TAG_MAX_SIZE];
+ struct TagData *next;
+ TypeId tid;
+ uint32_t count;
+ };
+
+ inline PacketTagList ();
+ inline PacketTagList (PacketTagList const &o);
+ inline PacketTagList &operator = (PacketTagList const &o);
+ inline ~PacketTagList ();
+
+ void Add (Tag const&tag) const;
+ bool Remove (Tag &tag);
+ bool Peek (Tag &tag) const;
+ inline void RemoveAll (void);
+
+ const struct PacketTagList::TagData *Head (void) const;
+
+private:
+
+ bool Remove (TypeId tid);
+ struct PacketTagList::TagData *AllocData (void) const;
+ void FreeData (struct TagData *data) const;
+
+ static struct PacketTagList::TagData *g_free;
+ static uint32_t g_nfree;
+
+ struct TagData *m_next;
+};
+
+} // namespace ns3
+
+/****************************************************
+ * Implementation of inline methods for performance
+ ****************************************************/
+
+namespace ns3 {
+
+PacketTagList::PacketTagList ()
+ : m_next ()
+{}
+
+PacketTagList::PacketTagList (PacketTagList const &o)
+ : m_next (o.m_next)
+{
+ if (m_next != 0)
+ {
+ m_next->count++;
+ }
+}
+
+PacketTagList &
+PacketTagList::operator = (PacketTagList const &o)
+{
+ // self assignment
+ if (m_next == o.m_next)
+ {
+ return *this;
+ }
+ RemoveAll ();
+ m_next = o.m_next;
+ if (m_next != 0)
+ {
+ m_next->count++;
+ }
+ return *this;
+}
+
+PacketTagList::~PacketTagList ()
+{
+ RemoveAll ();
+}
+
+void
+PacketTagList::RemoveAll (void)
+{
+ struct TagData *prev = 0;
+ for (struct TagData *cur = m_next; cur != 0; cur = cur->next)
+ {
+ cur->count--;
+ if (cur->count > 0)
+ {
+ break;
+ }
+ if (prev != 0)
+ {
+ FreeData (prev);
+ }
+ prev = cur;
+ }
+ if (prev != 0)
+ {
+ FreeData (prev);
+ }
+ m_next = 0;
+}
+
+} // namespace ns3
+
+#endif /* PACKET_TAG_LIST_H */
--- a/src/common/packet.cc Tue Apr 21 12:32:55 2009 +0200
+++ b/src/common/packet.cc Tue Apr 21 16:22:45 2009 +0400
@@ -28,22 +28,22 @@
uint32_t Packet::m_globalUid = 0;
TypeId
-TagIterator::Item::GetTypeId (void) const
+ByteTagIterator::Item::GetTypeId (void) const
{
return m_tid;
}
uint32_t
-TagIterator::Item::GetStart (void) const
+ByteTagIterator::Item::GetStart (void) const
{
return m_start;
}
uint32_t
-TagIterator::Item::GetEnd (void) const
+ByteTagIterator::Item::GetEnd (void) const
{
return m_end;
}
void
-TagIterator::Item::GetTag (Tag &tag) const
+ByteTagIterator::Item::GetTag (Tag &tag) const
{
if (tag.GetInstanceTypeId () != GetTypeId ())
{
@@ -51,31 +51,64 @@
}
tag.Deserialize (m_buffer);
}
-TagIterator::Item::Item (TypeId tid, uint32_t start, uint32_t end, TagBuffer buffer)
+ByteTagIterator::Item::Item (TypeId tid, uint32_t start, uint32_t end, TagBuffer buffer)
: m_tid (tid),
m_start (start),
m_end (end),
m_buffer (buffer)
{}
bool
-TagIterator::HasNext (void) const
+ByteTagIterator::HasNext (void) const
{
return m_current.HasNext ();
}
-TagIterator::Item
-TagIterator::Next (void)
+ByteTagIterator::Item
+ByteTagIterator::Next (void)
{
- TagList::Iterator::Item i = m_current.Next ();
- return TagIterator::Item (i.tid,
- i.start-m_current.GetOffsetStart (),
- i.end-m_current.GetOffsetStart (),
- i.buf);
+ ByteTagList::Iterator::Item i = m_current.Next ();
+ return ByteTagIterator::Item (i.tid,
+ i.start-m_current.GetOffsetStart (),
+ i.end-m_current.GetOffsetStart (),
+ i.buf);
}
-TagIterator::TagIterator (TagList::Iterator i)
+ByteTagIterator::ByteTagIterator (ByteTagList::Iterator i)
: m_current (i)
{}
+PacketTagIterator::PacketTagIterator (const struct PacketTagList::TagData *head)
+ : m_current (head)
+{}
+bool
+PacketTagIterator::HasNext (void) const
+{
+ return m_current != 0;
+}
+PacketTagIterator::Item
+PacketTagIterator::Next (void)
+{
+ NS_ASSERT (HasNext ());
+ const struct PacketTagList::TagData *prev = m_current;
+ m_current = m_current->next;
+ return PacketTagIterator::Item (prev);
+}
+
+PacketTagIterator::Item::Item (const struct PacketTagList::TagData *data)
+ : m_data (data)
+{}
+TypeId
+PacketTagIterator::Item::GetTypeId (void) const
+{
+ return m_data->tid;
+}
+void
+PacketTagIterator::Item::GetTag (Tag &tag) const
+{
+ NS_ASSERT (tag.GetInstanceTypeId () == m_data->tid);
+ tag.Deserialize (TagBuffer ((uint8_t*)m_data->data, (uint8_t*)m_data->data+PACKET_TAG_MAX_SIZE));
+}
+
+
void
Packet::Ref (void) const
{
@@ -102,7 +135,8 @@
Packet::Packet ()
: m_buffer (),
- m_tagList (),
+ m_byteTagList (),
+ m_packetTagList (),
m_metadata (m_globalUid, 0),
m_refCount (1)
{
@@ -111,7 +145,8 @@
Packet::Packet (const Packet &o)
: m_buffer (o.m_buffer),
- m_tagList (o.m_tagList),
+ m_byteTagList (o.m_byteTagList),
+ m_packetTagList (o.m_packetTagList),
m_metadata (o.m_metadata),
m_refCount (1)
{}
@@ -124,14 +159,16 @@
return *this;
}
m_buffer = o.m_buffer;
- m_tagList = o.m_tagList;
+ m_byteTagList = o.m_byteTagList;
+ m_packetTagList = o.m_packetTagList;
m_metadata = o.m_metadata;
return *this;
}
Packet::Packet (uint32_t size)
: m_buffer (size),
- m_tagList (),
+ m_byteTagList (),
+ m_packetTagList (),
m_metadata (m_globalUid, size),
m_refCount (1)
{
@@ -139,7 +176,8 @@
}
Packet::Packet (uint8_t const*buffer, uint32_t size)
: m_buffer (),
- m_tagList (),
+ m_byteTagList (),
+ m_packetTagList (),
m_metadata (m_globalUid, size),
m_refCount (1)
{
@@ -149,9 +187,11 @@
i.Write (buffer, size);
}
-Packet::Packet (const Buffer &buffer, const TagList &tagList, const PacketMetadata &metadata)
+Packet::Packet (const Buffer &buffer, const ByteTagList &byteTagList,
+ const PacketTagList &packetTagList, const PacketMetadata &metadata)
: m_buffer (buffer),
- m_tagList (tagList),
+ m_byteTagList (byteTagList),
+ m_packetTagList (packetTagList),
m_metadata (metadata),
m_refCount (1)
{}
@@ -166,7 +206,7 @@
PacketMetadata metadata = m_metadata.CreateFragment (start, end);
// again, call the constructor directly rather than
// through Create because it is private.
- return Ptr<Packet> (new Packet (buffer, m_tagList, metadata), false);
+ return Ptr<Packet> (new Packet (buffer, m_byteTagList, m_packetTagList, metadata), false);
}
uint32_t
@@ -184,8 +224,8 @@
bool resized = m_buffer.AddAtStart (size);
if (resized)
{
- m_tagList.AddAtStart (m_buffer.GetCurrentStartOffset () + size - orgStart,
- m_buffer.GetCurrentStartOffset () + size);
+ m_byteTagList.AddAtStart (m_buffer.GetCurrentStartOffset () + size - orgStart,
+ m_buffer.GetCurrentStartOffset () + size);
}
header.Serialize (m_buffer.Begin ());
m_metadata.AddHeader (header, size);
@@ -215,8 +255,8 @@
bool resized = m_buffer.AddAtEnd (size);
if (resized)
{
- m_tagList.AddAtEnd (m_buffer.GetCurrentStartOffset () - orgStart,
- m_buffer.GetCurrentEndOffset () - size);
+ m_byteTagList.AddAtEnd (m_buffer.GetCurrentStartOffset () - orgStart,
+ m_buffer.GetCurrentEndOffset () - size);
}
Buffer::Iterator end = m_buffer.End ();
trailer.Serialize (end);
@@ -247,12 +287,12 @@
uint32_t bEnd = packet->m_buffer.GetCurrentEndOffset ();
m_buffer.AddAtEnd (packet->m_buffer);
uint32_t appendPrependOffset = m_buffer.GetCurrentEndOffset () - packet->m_buffer.GetSize ();
- m_tagList.AddAtEnd (m_buffer.GetCurrentStartOffset () - aStart,
- appendPrependOffset);
- TagList copy = packet->m_tagList;
+ m_byteTagList.AddAtEnd (m_buffer.GetCurrentStartOffset () - aStart,
+ appendPrependOffset);
+ ByteTagList copy = packet->m_byteTagList;
copy.AddAtStart (m_buffer.GetCurrentEndOffset () - bEnd,
appendPrependOffset);
- m_tagList.Add (copy);
+ m_byteTagList.Add (copy);
m_metadata.AddAtEnd (packet->m_metadata);
}
void
@@ -263,8 +303,8 @@
bool resized = m_buffer.AddAtEnd (size);
if (resized)
{
- m_tagList.AddAtEnd (m_buffer.GetCurrentEndOffset () - orgEnd,
- m_buffer.GetCurrentEndOffset () - size);
+ m_byteTagList.AddAtEnd (m_buffer.GetCurrentEndOffset () - orgEnd,
+ m_buffer.GetCurrentEndOffset () - size);
}
m_metadata.AddPaddingAtEnd (size);
}
@@ -284,10 +324,10 @@
}
void
-Packet::RemoveAllTags (void)
+Packet::RemoveAllByteTags (void)
{
NS_LOG_FUNCTION (this);
- m_tagList.RemoveAll ();
+ m_byteTagList.RemoveAll ();
}
uint8_t const *
@@ -316,12 +356,12 @@
}
void
-Packet::PrintTags (std::ostream &os) const
+Packet::PrintByteTags (std::ostream &os) const
{
- TagIterator i = GetTagIterator ();
+ ByteTagIterator i = GetByteTagIterator ();
while (i.HasNext ())
{
- TagIterator::Item item = i.Next ();
+ ByteTagIterator::Item item = i.Next ();
os << item.GetTypeId ().GetName () << " [" << item.GetStart () << "-" << item.GetEnd () << "]";
Callback<ObjectBase *> constructor = item.GetTypeId ().GetConstructor ();
if (constructor.IsNull ())
@@ -544,29 +584,29 @@
}
void
-Packet::AddTag (const Tag &tag) const
+Packet::AddByteTag (const Tag &tag) const
{
NS_LOG_FUNCTION (this << &tag);
- TagList *list = const_cast<TagList *> (&m_tagList);
+ ByteTagList *list = const_cast<ByteTagList *> (&m_byteTagList);
TagBuffer buffer = list->Add (tag.GetInstanceTypeId (), tag.GetSerializedSize (),
- m_buffer.GetCurrentStartOffset (),
- m_buffer.GetCurrentEndOffset ());
+ m_buffer.GetCurrentStartOffset (),
+ m_buffer.GetCurrentEndOffset ());
tag.Serialize (buffer);
}
-TagIterator
-Packet::GetTagIterator (void) const
+ByteTagIterator
+Packet::GetByteTagIterator (void) const
{
- return TagIterator (m_tagList.Begin (m_buffer.GetCurrentStartOffset (), m_buffer.GetCurrentEndOffset ()));
+ return ByteTagIterator (m_byteTagList.Begin (m_buffer.GetCurrentStartOffset (), m_buffer.GetCurrentEndOffset ()));
}
bool
-Packet::FindFirstMatchingTag (Tag &tag) const
+Packet::FindFirstMatchingByteTag (Tag &tag) const
{
TypeId tid = tag.GetInstanceTypeId ();
- TagIterator i = GetTagIterator ();
+ ByteTagIterator i = GetByteTagIterator ();
while (i.HasNext ())
{
- TagIterator::Item item = i.Next ();
+ ByteTagIterator::Item item = i.Next ();
if (tid == item.GetTypeId ())
{
item.GetTag (tag);
@@ -576,6 +616,59 @@
return false;
}
+void
+Packet::AddPacketTag (const Tag &tag) const
+{
+ m_packetTagList.Add (tag);
+}
+bool
+Packet::RemovePacketTag (Tag &tag)
+{
+ bool found = m_packetTagList.Remove (tag);
+ return found;
+}
+bool
+Packet::PeekPacketTag (Tag &tag) const
+{
+ bool found = m_packetTagList.Peek (tag);
+ return found;
+}
+void
+Packet::RemoveAllPacketTags (void)
+{
+ m_packetTagList.RemoveAll ();
+}
+
+void
+Packet::PrintPacketTags (std::ostream &os) const
+{
+ PacketTagIterator i = GetPacketTagIterator ();
+ while (i.HasNext ())
+ {
+ PacketTagIterator::Item item = i.Next ();
+ NS_ASSERT (item.GetTypeId ().HasConstructor ());
+ Callback<ObjectBase *> constructor = item.GetTypeId ().GetConstructor ();
+ NS_ASSERT (!constructor.IsNull ());
+ ObjectBase *instance = constructor ();
+ Tag *tag = dynamic_cast<Tag *> (instance);
+ NS_ASSERT (tag != 0);
+ item.GetTag (*tag);
+ tag->Print (os);
+ delete tag;
+ if (i.HasNext ())
+ {
+ os << " ";
+ }
+ }
+}
+
+PacketTagIterator
+Packet::GetPacketTagIterator (void) const
+{
+ return PacketTagIterator (m_packetTagList.Head ());
+}
+
+
std::ostream& operator<< (std::ostream& os, const Packet &packet)
{
packet.Print (os);
@@ -585,8 +678,6 @@
} // namespace ns3
-
-
#ifdef RUN_SELF_TESTS
#include "ns3/test.h"
@@ -773,14 +864,14 @@
namespace ns3 {
-class PacketTest: public Test
+static class PacketTest: public Test
{
public:
PacketTest ();
virtual bool RunTests (void);
private:
bool DoCheck (Ptr<const Packet> p, const char *file, int line, uint32_t n, ...);
-};
+} g_packetTest;
PacketTest::PacketTest ()
@@ -802,11 +893,11 @@
}
va_end (ap);
- TagIterator i = p->GetTagIterator ();
+ ByteTagIterator i = p->GetByteTagIterator ();
uint32_t j = 0;
while (i.HasNext () && j < expected.size ())
{
- TagIterator::Item item = i.Next ();
+ ByteTagIterator::Item item = i.Next ();
struct Expected e = expected[j];
std::ostringstream oss;
oss << "anon::ATestTag<" << e.n << ">";
@@ -845,12 +936,12 @@
Ptr<const Packet> p = Create<Packet> (1000);
- p->AddTag (ATestTag<1> ());
+ p->AddByteTag (ATestTag<1> ());
CHECK (p, 1, E (1, 0, 1000));
Ptr<const Packet> copy = p->Copy ();
CHECK (copy, 1, E (1, 0, 1000));
- p->AddTag (ATestTag<2> ());
+ p->AddByteTag (ATestTag<2> ());
CHECK (p, 2, E (1, 0, 1000), E(2, 0, 1000));
CHECK (copy, 1, E (1, 0, 1000));
@@ -861,7 +952,7 @@
CHECK (&c0, 1, E (1, 0, 1000));
CHECK (&c1, 1, E (1, 0, 1000));
CHECK (copy, 1, E (1, 0, 1000));
- c0.AddTag (ATestTag<10> ());
+ c0.AddByteTag (ATestTag<10> ());
CHECK (&c0, 2, E (1, 0, 1000), E (10, 0, 1000));
CHECK (&c1, 1, E (1, 0, 1000));
CHECK (copy, 1, E (1, 0, 1000));
@@ -870,11 +961,11 @@
Ptr<Packet> frag0 = p->CreateFragment (0, 10);
Ptr<Packet> frag1 = p->CreateFragment (10, 90);
Ptr<const Packet> frag2 = p->CreateFragment (100, 900);
- frag0->AddTag (ATestTag<3> ());
+ frag0->AddByteTag (ATestTag<3> ());
CHECK (frag0, 3, E (1, 0, 10), E(2, 0, 10), E (3, 0, 10));
- frag1->AddTag (ATestTag<4> ());
+ frag1->AddByteTag (ATestTag<4> ());
CHECK (frag1, 3, E (1, 0, 90), E(2, 0, 90), E (4, 0, 90));
- frag2->AddTag (ATestTag<5> ());
+ frag2->AddByteTag (ATestTag<5> ());
CHECK (frag2, 3, E (1, 0, 900), E(2, 0, 900), E (5, 0, 900));
frag1->AddAtEnd (frag2);
@@ -894,7 +985,7 @@
frag0 = 0;
p = Create<Packet> (1000);
- p->AddTag (ATestTag<20> ());
+ p->AddByteTag (ATestTag<20> ());
CHECK (p, 1, E (20, 0, 1000));
frag0 = p->CreateFragment (10, 90);
CHECK (p, 1, E (20, 0, 1000));
@@ -905,7 +996,7 @@
{
Ptr<Packet> tmp = Create<Packet> (100);
- tmp->AddTag (ATestTag<20> ());
+ tmp->AddByteTag (ATestTag<20> ());
CHECK (tmp, 1, E (20, 0, 100));
tmp->AddHeader (ATestHeader<10> ());
CHECK (tmp, 1, E (20, 10, 110));
@@ -916,7 +1007,7 @@
CHECK (tmp, 1, E (20, 10, 110));
tmp = Create<Packet> (100);
- tmp->AddTag (ATestTag<20> ());
+ tmp->AddByteTag (ATestTag<20> ());
CHECK (tmp, 1, E (20, 0, 100));
tmp->AddTrailer (ATestTrailer<10> ());
CHECK (tmp, 1, E (20, 0, 100));
@@ -931,7 +1022,7 @@
{
Ptr<Packet> tmp = Create<Packet> (0);
tmp->AddHeader (ATestHeader<156> ());
- tmp->AddTag (ATestTag<20> ());
+ tmp->AddByteTag (ATestTag<20> ());
CHECK (tmp, 1, E (20, 0, 156));
tmp->RemoveAtStart (120);
CHECK (tmp, 1, E (20, 0, 36));
@@ -942,29 +1033,56 @@
{
Ptr<Packet> tmp = Create<Packet> (0);
- tmp->AddTag (ATestTag<20> ());
+ tmp->AddByteTag (ATestTag<20> ());
CHECK (tmp, 0, E (20, 0, 0));
}
{
Ptr<Packet> tmp = Create<Packet> (1000);
- tmp->AddTag (ATestTag<20> ());
+ tmp->AddByteTag (ATestTag<20> ());
CHECK (tmp, 1, E (20, 0, 1000));
tmp->RemoveAtStart (1000);
CHECK (tmp, 0, E (0,0,0));
Ptr<Packet> a = Create<Packet> (10);
- a->AddTag (ATestTag<10> ());
+ a->AddByteTag (ATestTag<10> ());
CHECK (a, 1, E (10, 0, 10));
tmp->AddAtEnd (a);
CHECK (tmp, 1, E (10, 0, 10));
}
-
+
+ {
+ Packet p;
+ ATestTag<10> a;
+ p.AddPacketTag (a);
+ NS_TEST_ASSERT (p.PeekPacketTag (a));
+ ATestTag<11> b;
+ p.AddPacketTag (b);
+ NS_TEST_ASSERT (p.PeekPacketTag (b));
+ NS_TEST_ASSERT (p.PeekPacketTag (a));
+ Packet copy = p;
+ NS_TEST_ASSERT (copy.PeekPacketTag (b));
+ NS_TEST_ASSERT (copy.PeekPacketTag (a));
+ ATestTag<12> c;
+ NS_TEST_ASSERT (!copy.PeekPacketTag (c));
+ copy.AddPacketTag (c);
+ NS_TEST_ASSERT (copy.PeekPacketTag (c));
+ NS_TEST_ASSERT (copy.PeekPacketTag (b));
+ NS_TEST_ASSERT (copy.PeekPacketTag (a));
+ NS_TEST_ASSERT (!p.PeekPacketTag (c));
+ copy.RemovePacketTag (b);
+ NS_TEST_ASSERT (!copy.PeekPacketTag (b));
+ NS_TEST_ASSERT (p.PeekPacketTag (b));
+ p.RemovePacketTag (a);
+ NS_TEST_ASSERT (!p.PeekPacketTag (a));
+ NS_TEST_ASSERT (copy.PeekPacketTag (a));
+ NS_TEST_ASSERT (!p.PeekPacketTag (c));
+ NS_TEST_ASSERT (copy.PeekPacketTag (c));
+ p.RemoveAllPacketTags ();
+ NS_TEST_ASSERT (!p.PeekPacketTag (b));
+ }
return result;
}
-
-static PacketTest g_packetTest;
-
-}; // namespace ns3
+} // namespace ns3
#endif /* RUN_SELF_TESTS */
--- a/src/common/packet.h Tue Apr 21 12:32:55 2009 +0200
+++ b/src/common/packet.h Tue Apr 21 16:22:45 2009 +0400
@@ -26,7 +26,8 @@
#include "trailer.h"
#include "packet-metadata.h"
#include "tag.h"
-#include "tag-list.h"
+#include "byte-tag-list.h"
+#include "packet-tag-list.h"
#include "ns3/callback.h"
#include "ns3/assert.h"
#include "ns3/ptr.h"
@@ -45,7 +46,7 @@
*
* This is a java-style iterator.
*/
-class TagIterator
+class ByteTagIterator
{
public:
/**
@@ -81,7 +82,7 @@
*/
void GetTag (Tag &tag) const;
private:
- friend class TagIterator;
+ friend class ByteTagIterator;
Item (TypeId tid, uint32_t start, uint32_t end, TagBuffer buffer);
TypeId m_tid;
uint32_t m_start;
@@ -98,16 +99,63 @@
Item Next (void);
private:
friend class Packet;
- TagIterator (TagList::Iterator i);
- TagList::Iterator m_current;
+ ByteTagIterator (ByteTagList::Iterator i);
+ ByteTagList::Iterator m_current;
+};
+
+/**
+ * \ingroup packet
+ * \brief Iterator over the set of 'packet' tags in a packet
+ *
+ * This is a java-style iterator.
+ */
+class PacketTagIterator
+{
+public:
+ /**
+ * Identifies a tag within a packet.
+ */
+ class Item
+ {
+ public:
+ /**
+ * \returns the ns3::TypeId associated to this tag.
+ */
+ TypeId GetTypeId (void) const;
+ /**
+ * \param tag the user tag to which the data should be copied.
+ *
+ * Read the requested tag and store it in the user-provided
+ * tag instance. This method will crash if the type of the
+ * tag provided by the user does not match the type of
+ * the underlying tag.
+ */
+ void GetTag (Tag &tag) const;
+ private:
+ friend class PacketTagIterator;
+ Item (const struct PacketTagList::TagData *data);
+ const struct PacketTagList::TagData *m_data;
+ };
+ /**
+ * \returns true if calling Next is safe, false otherwise.
+ */
+ bool HasNext (void) const;
+ /**
+ * \returns the next item found and prepare for the next one.
+ */
+ Item Next (void);
+private:
+ friend class Packet;
+ PacketTagIterator (const struct PacketTagList::TagData *head);
+ const struct PacketTagList::TagData *m_current;
};
/**
* \ingroup packet
* \brief network packets
*
- * Each network packet contains a byte buffer, a set of tags, and
- * metadata.
+ * Each network packet contains a byte buffer, a set of byte tags, a set of
+ * packet tags, and metadata.
*
* - The byte buffer stores the serialized content of the headers and trailers
* added to a packet. The serialized representation of these headers is expected
@@ -115,17 +163,23 @@
* forces you to do this) which means that the content of a packet buffer
* is expected to be that of a real packet.
*
- * - Each tag tags a subset of the bytes in the packet byte buffer with the
- * information stored in the tag. A classic example of a tag is a FlowIdTag
- * which contains a flow id: the set of bytes tagged by this tag implicitely
- * belong to the attached flow id.
- *
* - The metadata describes the type of the headers and trailers which
* were serialized in the byte buffer. The maintenance of metadata is
* optional and disabled by default. To enable it, you must call
* Packet::EnableMetadata and this will allow you to get non-empty
* output from Packet::Print and Packet::Print.
*
+ * - The set of tags contain simulation-specific information which cannot
+ * be stored in the packet byte buffer because the protocol headers or trailers
+ * have no standard-conformant field for this information. So-called
+ * 'byte' tags are used to tag a subset of the bytes in the packet byte buffer
+ * while 'packet' tags are used to tag the packet itself. The main difference
+ * between these two kinds of tags is what happens when packets are copied,
+ * fragmented, and reassembled: 'byte' tags follow bytes while 'packet' tags
+ * follow packets. A classic example of a 'byte' tag is a FlowIdTag
+ * which contains a flow id: the set of bytes tagged by this tag implicitely
+ * belong to the attached flow id.
+ *
* Implementing a new type of Header or Trailer for a new protocol is
* pretty easy and is a matter of creating a subclass of the ns3::Header
* or of the ns3::Trailer base class, and implementing the methods
@@ -236,13 +290,6 @@
* \returns the number of bytes read from the end of the packet.
*/
uint32_t PeekTrailer (Trailer &trailer);
- /**
- * \param os output stream in which the data should be printed.
- *
- * Iterate over the tags present in this packet, and
- * invoke the Print method of each tag stored in the packet.
- */
- void PrintTags (std::ostream &os) const;
/**
* Concatenate the input packet at the end of the current
@@ -390,11 +437,11 @@
* totally evil to allow a trace sink to modify the content of a
* packet).
*/
- void AddTag (const Tag &tag) const;
+ void AddByteTag (const Tag &tag) const;
/**
- * \returns an iterator over the set of tags included in this packet.
+ * \returns an iterator over the set of byte tags included in this packet.
*/
- TagIterator GetTagIterator (void) const;
+ ByteTagIterator GetByteTagIterator (void) const;
/**
* \param tag the tag to search in this packet
* \returns true if the requested tag type was found, false otherwise.
@@ -402,17 +449,78 @@
* If the requested tag type is found, it is copied in the user's
* provided tag instance.
*/
- bool FindFirstMatchingTag (Tag &tag) const;
+ bool FindFirstMatchingByteTag (Tag &tag) const;
/**
* Remove all the tags stored in this packet.
*/
- void RemoveAllTags (void);
+ void RemoveAllByteTags (void);
+
+ /**
+ * \param os output stream in which the data should be printed.
+ *
+ * Iterate over the tags present in this packet, and
+ * invoke the Print method of each tag stored in the packet.
+ */
+ void PrintByteTags (std::ostream &os) const;
+
+ /**
+ * \param tag the tag to store in this packet
+ *
+ * Add a tag to this packet. This method calls the
+ * Tag::GetSerializedSize and, then, Tag::Serialize.
+ *
+ * Note that this method is const, that is, it does not
+ * modify the state of this packet, which is fairly
+ * un-intuitive.
+ *
+ * \sa AddTag
+ */
+ void AddPacketTag (const Tag &tag) const;
+ /**
+ * \param tag the tag to remove from this packet
+ * \returns true if the requested tag is found, false
+ * otherwise.
+ *
+ * Remove a tag from this packet. This method calls
+ * Tag::Deserialize if the tag is found.
+ */
+ bool RemovePacketTag (Tag &tag);
+ /**
+ * \param tag the tag to search in this packet
+ * \returns true if the requested tag is found, false
+ * otherwise.
+ *
+ * Search a matching tag and call Tag::Deserialize if it is found.
+ */
+ bool PeekPacketTag (Tag &tag) const;
+ /**
+ * Remove all packet tags.
+ */
+ void RemoveAllPacketTags (void);
+
+ /**
+ * \param os the stream in which we want to print data.
+ *
+ * Print the list of 'packet' tags.
+ *
+ * \sa Packet::AddPacketTag, Packet::RemovePacketTag, Packet::PeekPacketTag,
+ * Packet::RemoveAllPacketTags
+ */
+ void PrintPacketTags (std::ostream &os) const;
+
+ /**
+ * \returns an object which can be used to iterate over the list of
+ * packet tags.
+ */
+ PacketTagIterator GetPacketTagIterator (void) const;
private:
- Packet (const Buffer &buffer, const TagList &tagList, const PacketMetadata &metadata);
+ Packet (const Buffer &buffer, const ByteTagList &byteTagList,
+ const PacketTagList &packetTagList, const PacketMetadata &metadata);
Buffer m_buffer;
- TagList m_tagList;
+ ByteTagList m_byteTagList;
+ PacketTagList m_packetTagList;
PacketMetadata m_metadata;
mutable uint32_t m_refCount;
static uint32_t m_globalUid;
@@ -437,11 +545,14 @@
* - ns3::Packet::AddHeader
* - ns3::Packet::AddTrailer
* - both versions of ns3::Packet::AddAtEnd
+ * - ns3::Packet::RemovePacketTag
*
* Non-dirty operations:
* - ns3::Packet::AddTag
* - ns3::Packet::RemoveAllTags
* - ns3::Packet::PeekTag
+ * - ns3::Packet::RemoveAllPacketTags
+ * - ns3::Packet::PeekPacketTag
* - ns3::Packet::RemoveHeader
* - ns3::Packet::RemoveTrailer
* - ns3::Packet::CreateFragment
--- a/src/common/tag-list.cc Tue Apr 21 12:32:55 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,421 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2008 INRIA
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation;
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-#include "tag-list.h"
-#include "ns3/log.h"
-#include <vector>
-#include <string.h>
-
-NS_LOG_COMPONENT_DEFINE ("TagList");
-
-#define USE_FREE_LIST 1
-#define FREE_LIST_SIZE 1000
-#define OFFSET_MAX (2147483647)
-
-namespace ns3 {
-
-struct TagListData {
- uint32_t size;
- uint32_t count;
- uint32_t dirty;
- uint8_t data[4];
-};
-
-#ifdef USE_FREE_LIST
-static class TagListDataFreeList : public std::vector<struct TagListData *>
-{
-public:
- ~TagListDataFreeList ();
-} g_freeList;
-static uint32_t g_maxSize = 0;
-
-TagListDataFreeList::~TagListDataFreeList ()
-{
- for (TagListDataFreeList::iterator i = begin ();
- i != end (); i++)
- {
- uint8_t *buffer = (uint8_t *)(*i);
- delete [] buffer;
- }
-}
-#endif /* USE_FREE_LIST */
-
-TagList::Iterator::Item::Item (TagBuffer buf_)
- : buf (buf_)
-{}
-
-bool
-TagList::Iterator::HasNext (void) const
-{
- return m_current < m_end;
-}
-struct TagList::Iterator::Item
-TagList::Iterator::Next (void)
-{
- NS_ASSERT (HasNext ());
- struct Item item = Item (TagBuffer (m_current+16, m_end));
- item.tid.SetUid (m_nextTid);
- item.size = m_nextSize;
- item.start = std::max (m_nextStart, m_offsetStart);
- item.end = std::min (m_nextEnd, m_offsetEnd);
- m_current += 4 + 4 + 4 + 4 + item.size;
- item.buf.TrimAtEnd (m_end - m_current);
- PrepareForNext ();
- return item;
-}
-void
-TagList::Iterator::PrepareForNext (void)
-{
- while (m_current < m_end)
- {
- TagBuffer buf = TagBuffer (m_current, m_end);
- m_nextTid = buf.ReadU32 ();
- m_nextSize = buf.ReadU32 ();
- m_nextStart = buf.ReadU32 ();
- m_nextEnd = buf.ReadU32 ();
- if (m_nextStart >= m_offsetEnd || m_nextEnd <= m_offsetStart)
- {
- m_current += 4 + 4 + 4 + 4 + m_nextSize;
- }
- else
- {
- break;
- }
- }
-}
-TagList::Iterator::Iterator (uint8_t *start, uint8_t *end, int32_t offsetStart, int32_t offsetEnd)
- : m_current (start),
- m_end (end),
- m_offsetStart (offsetStart),
- m_offsetEnd (offsetEnd)
-{
- PrepareForNext ();
-}
-
-uint32_t
-TagList::Iterator::GetOffsetStart (void) const
-{
- return m_offsetStart;
-}
-
-
-TagList::TagList ()
- : m_used (0),
- m_data (0)
-{
- NS_LOG_FUNCTION (this);
-}
-TagList::TagList (const TagList &o)
- : m_used (o.m_used),
- m_data (o.m_data)
-{
- NS_LOG_FUNCTION (this << &o);
- if (m_data != 0)
- {
- m_data->count++;
- }
-}
-TagList &
-TagList::operator = (const TagList &o)
-{
- NS_LOG_FUNCTION (this << &o);
- if (this == &o)
- {
- return *this;
- }
-
- Deallocate (m_data);
- m_data = o.m_data;
- m_used = o.m_used;
- if (m_data != 0)
- {
- m_data->count++;
- }
- return *this;
-}
-TagList::~TagList ()
-{
- NS_LOG_FUNCTION (this);
- Deallocate (m_data);
- m_data = 0;
- m_used = 0;
-}
-
-TagBuffer
-TagList::Add (TypeId tid, uint32_t bufferSize, int32_t start, int32_t end)
-{
- NS_LOG_FUNCTION (this << tid << bufferSize << start << end);
- uint32_t spaceNeeded = m_used + bufferSize + 4 + 4 + 4 + 4;
- NS_ASSERT (m_used <= spaceNeeded);
- if (m_data == 0)
- {
- m_data = Allocate (spaceNeeded);
- m_used = 0;
- }
- else if (m_data->size < spaceNeeded ||
- (m_data->count != 1 && m_data->dirty != m_used))
- {
- struct TagListData *newData = Allocate (spaceNeeded);
- memcpy (&newData->data, &m_data->data, m_used);
- Deallocate (m_data);
- m_data = newData;
- }
- TagBuffer tag = TagBuffer (&m_data->data[m_used],
- &m_data->data[spaceNeeded]);
- tag.WriteU32 (tid.GetUid ());
- tag.WriteU32 (bufferSize);
- tag.WriteU32 (start);
- tag.WriteU32 (end);
- m_used = spaceNeeded;
- m_data->dirty = m_used;
- return tag;
-}
-
-void
-TagList::Add (const TagList &o)
-{
- NS_LOG_FUNCTION (this << &o);
- TagList::Iterator i = o.BeginAll ();
- while (i.HasNext ())
- {
- TagList::Iterator::Item item = i.Next ();
- TagBuffer buf = Add (item.tid, item.size, item.start, item.end);
- buf.CopyFrom (item.buf);
- }
-}
-
-void
-TagList::RemoveAll (void)
-{
- NS_LOG_FUNCTION (this);
- Deallocate (m_data);
- m_data = 0;
- m_used = 0;
-}
-
-TagList::Iterator
-TagList::BeginAll (void) const
-{
- NS_LOG_FUNCTION (this);
- // I am not totally sure but I might need to use
- // INT32_MIN instead of zero below.
- return Begin (0, OFFSET_MAX);
-}
-
-TagList::Iterator
-TagList::Begin (int32_t offsetStart, int32_t offsetEnd) const
-{
- NS_LOG_FUNCTION (this << offsetStart << offsetEnd);
- if (m_data == 0)
- {
- return Iterator (0, 0, offsetStart, offsetEnd);
- }
- else
- {
- return Iterator (m_data->data, &m_data->data[m_used], offsetStart, offsetEnd);
- }
-}
-
-bool
-TagList::IsDirtyAtEnd (int32_t appendOffset)
-{
- NS_LOG_FUNCTION (this << appendOffset);
- TagList::Iterator i = BeginAll ();
- while (i.HasNext ())
- {
- TagList::Iterator::Item item = i.Next ();
- if (item.end > appendOffset)
- {
- return true;
- }
- }
- return false;
-}
-
-bool
-TagList::IsDirtyAtStart (int32_t prependOffset)
-{
- NS_LOG_FUNCTION (this << prependOffset);
- TagList::Iterator i = BeginAll ();
- while (i.HasNext ())
- {
- TagList::Iterator::Item item = i.Next ();
- if (item.start < prependOffset)
- {
- return true;
- }
- }
- return false;
-}
-
-void
-TagList::AddAtEnd (int32_t adjustment, int32_t appendOffset)
-{
- NS_LOG_FUNCTION (this << adjustment << appendOffset);
- if (adjustment == 0 && !IsDirtyAtEnd (appendOffset))
- {
- return;
- }
- TagList list;
- TagList::Iterator i = BeginAll ();
- while (i.HasNext ())
- {
- TagList::Iterator::Item item = i.Next ();
- item.start += adjustment;
- item.end += adjustment;
-
- if (item.start >= appendOffset)
- {
- continue;
- }
- else if (item.start < appendOffset && item.end > appendOffset)
- {
- item.end = appendOffset;
- }
- else
- {
- // nothing to do.
- }
- TagBuffer buf = list.Add (item.tid, item.size, item.start, item.end);
- buf.CopyFrom (item.buf);
- }
- *this = list;
-}
-
-void
-TagList::AddAtStart (int32_t adjustment, int32_t prependOffset)
-{
- NS_LOG_FUNCTION (this << adjustment << prependOffset);
- if (adjustment == 0 && !IsDirtyAtStart (prependOffset))
- {
- return;
- }
- TagList list;
- TagList::Iterator i = BeginAll ();
- while (i.HasNext ())
- {
- TagList::Iterator::Item item = i.Next ();
- item.start += adjustment;
- item.end += adjustment;
-
- if (item.end <= prependOffset)
- {
- continue;
- }
- else if (item.end > prependOffset && item.start < prependOffset)
- {
- item.start = prependOffset;
- }
- else
- {
- // nothing to do.
- }
- TagBuffer buf = list.Add (item.tid, item.size, item.start, item.end);
- buf.CopyFrom (item.buf);
- }
- *this = list;
-}
-
-#ifdef USE_FREE_LIST
-
-struct TagListData *
-TagList::Allocate (uint32_t size)
-{
- NS_LOG_FUNCTION (this << size);
- while (!g_freeList.empty ())
- {
- struct TagListData *data = g_freeList.back ();
- g_freeList.pop_back ();
- NS_ASSERT (data != 0);
- if (data->size >= size)
- {
- data->count = 1;
- data->dirty = 0;
- return data;
- }
- uint8_t *buffer = (uint8_t *)data;
- delete [] buffer;
- }
- uint8_t *buffer = new uint8_t [std::max (size, g_maxSize) + sizeof (struct TagListData) - 4];
- struct TagListData *data = (struct TagListData *)buffer;
- data->count = 1;
- data->size = size;
- data->dirty = 0;
- return data;
-}
-
-void
-TagList::Deallocate (struct TagListData *data)
-{
- NS_LOG_FUNCTION (this << data);
- if (data == 0)
- {
- return;
- }
- g_maxSize = std::max (g_maxSize, data->size);
- data->count--;
- if (data->count == 0)
- {
- if (g_freeList.size () > FREE_LIST_SIZE ||
- data->size < g_maxSize)
- {
- uint8_t *buffer = (uint8_t *)data;
- delete [] buffer;
- }
- else
- {
- g_freeList.push_back (data);
- }
- }
-}
-
-#else /* USE_FREE_LIST */
-
-struct TagListData *
-TagList::Allocate (uint32_t size)
-{
- NS_LOG_FUNCTION (this << size);
- uint8_t *buffer = new uint8_t [size + sizeof (struct TagListData) - 4];
- struct TagListData *data = (struct TagListData *)buffer;
- data->count = 1;
- data->size = size;
- data->dirty = 0;
- return data;
-}
-
-void
-TagList::Deallocate (struct TagListData *data)
-{
- NS_LOG_FUNCTION (this << data);
- if (data == 0)
- {
- return;
- }
- data->count--;
- if (data->count == 0)
- {
- uint8_t *buffer = (uint8_t *)data;
- delete [] buffer;
- }
-}
-
-#endif /* USE_FREE_LIST */
-
-
-} // namespace ns3
--- a/src/common/tag-list.h Tue Apr 21 12:32:55 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,170 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2008 INRIA
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation;
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-#ifndef TAG_LIST_H
-#define TAG_LIST_H
-
-#include <stdint.h>
-#include "ns3/type-id.h"
-#include "tag-buffer.h"
-
-namespace ns3 {
-
-struct TagListData;
-
-/**
- * \ingroup packet
- *
- * \brief keep track of the tags stored in a packet.
- *
- * This class is mostly private to the Packet implementation and users
- * should never have to access it directly.
- *
- * \internal
- * The implementation of this class is a bit tricky so, there are a couple
- * of things to keep in mind here:
- *
- * - it stores all tags in a single byte buffer: each tag is stored
- * as 4 32bit integers (TypeId, tag data size, start, end) followed
- * by the tag data as generated by Tag::Serialize.
- *
- * - the struct TagListData structure which contains the tag byte buffer
- * is shared and, thus, reference-counted. This data structure is unshared
- * as-needed to emulate COW semantics.
- *
- * - each tag tags a unique set of bytes identified by the pair of offsets
- * (start,end). These offsets are provided by Buffer::GetCurrentStartOffset
- * and Buffer::GetCurrentEndOffset which means that they are relative to
- * the start of the 'virtual byte buffer' as explained in the documentation
- * for the ns3::Buffer class. Whenever the origin of the offset of the Buffer
- * instance associated to this TagList instance changes, the Buffer class
- * reports this to its container Packet class as a bool return value
- * in Buffer::AddAtStart and Buffer::AddAtEnd. In both cases, when this happens
- * the Packet class calls TagList::AddAtEnd and TagList::AddAtStart to update
- * the byte offsets of each tag in the TagList.
- *
- * - whenever bytes are removed from the packet byte buffer, the TagList offsets
- * are never updated because we rely on the fact that they will be updated in
- * either the next call to Packet::AddHeader or Packet::AddTrailer or when
- * the user iterates the tag list with Packet::GetTagIterator and
- * TagIterator::Next.
- */
-class TagList
-{
-public:
-
- class Iterator
- {
- public:
- struct Item
- {
- TypeId tid;
- uint32_t size;
- int32_t start;
- int32_t end;
- TagBuffer buf;
- Item (TagBuffer buf);
- private:
- friend class TagList;
- friend class TagList::Iterator;
- };
- bool HasNext (void) const;
- struct TagList::Iterator::Item Next (void);
- uint32_t GetOffsetStart (void) const;
- private:
- friend class TagList;
- Iterator (uint8_t *start, uint8_t *end, int32_t offsetStart, int32_t offsetEnd);
- void PrepareForNext (void);
- uint8_t *m_current;
- uint8_t *m_end;
- int32_t m_offsetStart;
- int32_t m_offsetEnd;
- uint32_t m_nextTid;
- uint32_t m_nextSize;
- int32_t m_nextStart;
- int32_t m_nextEnd;
- };
-
- TagList ();
- TagList (const TagList &o);
- TagList &operator = (const TagList &o);
- ~TagList ();
-
- /**
- * \param tid the typeid of the tag added
- * \param bufferSize the size of the tag when its serialization will
- * be completed. Typically, the return value of Tag::GetSerializedSize
- * \param start offset which uniquely identifies the first byte tagged by this tag.
- * \param end offset which uniquely identifies the last byte tagged by this tag.
- * \returns a buffer which can be used to write the tag data.
- *
- *
- */
- TagBuffer Add (TypeId tid, uint32_t bufferSize, int32_t start, int32_t end);
-
- /**
- * \param o the other list of tags to aggregate.
- *
- * Aggregate the two lists of tags.
- */
- void Add (const TagList &o);
-
- void RemoveAll (void);
-
- /**
- * \param offsetStart the offset which uniquely identifies the first data byte
- * present in the byte buffer associated to this TagList.
- * \param offsetEnd the offset which uniquely identifies the last data byte
- * present in the byte buffer associated to this TagList.
- * \returns an iterator
- *
- * The returned iterator will allow you to loop through the set of tags present
- * in this list: the boundaries of each tag as reported by their start and
- * end offsets will be included within the input offsetStart and offsetEnd.
- */
- TagList::Iterator Begin (int32_t offsetStart, int32_t offsetEnd) const;
-
- /**
- * Adjust the offsets stored internally by the adjustment delta and
- * make sure that all offsets are smaller than appendOffset which represents
- * the location where new bytes have been added to the byte buffer.
- */
- void AddAtEnd (int32_t adjustment, int32_t appendOffset);
- /**
- * Adjust the offsets stored internally by the adjustment delta and
- * make sure that all offsets are bigger than prependOffset which represents
- * the location where new bytes have been added to the byte buffer.
- */
- void AddAtStart (int32_t adjustment, int32_t prependOffset);
-
-private:
- bool IsDirtyAtEnd (int32_t appendOffset);
- bool IsDirtyAtStart (int32_t prependOffset);
- TagList::Iterator BeginAll (void) const;
-
- struct TagListData *Allocate (uint32_t size);
- void Deallocate (struct TagListData *data);
-
- uint16_t m_used;
- struct TagListData *m_data;
-};
-
-} // namespace ns3
-
-#endif /* TAG_LIST_H */
--- a/src/common/tag.h Tue Apr 21 12:32:55 2009 +0200
+++ b/src/common/tag.h Tue Apr 21 16:22:45 2009 +0400
@@ -41,8 +41,8 @@
/**
* \returns the number of bytes required to serialize the data of the tag.
*
- * This method is typically invoked by Packet::AddTag just prior to calling
- * Tag::Serialize.
+ * This method is typically invoked by Packet::AddPacketTag or Packet::AddByteTag
+ * just prior to calling Tag::Serialize.
*/
virtual uint32_t GetSerializedSize (void) const = 0;
/**
@@ -65,7 +65,8 @@
/**
* \param os the stream to print to
*
- * This method is typically invoked from the Packet::PrintTags method
+ * This method is typically invoked from the Packet::PrintByteTags
+ * or Packet::PrintPacketTags methods.
*/
virtual void Print (std::ostream &os) const = 0;
};
--- a/src/common/wscript Tue Apr 21 12:32:55 2009 +0200
+++ b/src/common/wscript Tue Apr 21 16:22:45 2009 +0400
@@ -14,8 +14,9 @@
'data-rate.cc',
'error-model.cc',
'tag.cc',
- 'tag-list.cc',
+ 'byte-tag-list.cc',
'tag-buffer.cc',
+ 'packet-tag-list.cc',
]
headers = bld.new_task_gen('ns3header')
@@ -31,6 +32,7 @@
'data-rate.h',
'error-model.h',
'tag.h',
- 'tag-list.h',
+ 'byte-tag-list.h',
'tag-buffer.h',
+ 'packet-tag-list.h',
]
--- a/src/contrib/delay-jitter-estimation.cc Tue Apr 21 12:32:55 2009 +0200
+++ b/src/contrib/delay-jitter-estimation.cc Tue Apr 21 16:22:45 2009 +0400
@@ -83,14 +83,14 @@
DelayJitterEstimation::PrepareTx (Ptr<const Packet> packet)
{
DelayJitterEstimationTimestampTag tag;
- packet->AddTag (tag);
+ packet->AddByteTag (tag);
}
void
DelayJitterEstimation::RecordRx (Ptr<const Packet> packet)
{
DelayJitterEstimationTimestampTag tag;
bool found;
- found = packet->FindFirstMatchingTag (tag);
+ found = packet->FindFirstMatchingByteTag (tag);
if (!found)
{
return;
--- a/src/core/test.h Tue Apr 21 12:32:55 2009 +0200
+++ b/src/core/test.h Tue Apr 21 16:22:45 2009 +0400
@@ -110,7 +110,7 @@
#define NS_TEST_ASSERT_EQUAL_FILELINE(got, expected, file, line) \
do { \
- if ((got) != (expected)) \
+ if (! ((got) == (expected))) \
{ \
Failure () << file << ":" <<line \
<< ": expected " << (expected) \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/airtime-metric.cc Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,38 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#include "airtime-metric.h"
+#include "ns3/wifi-remote-station-manager.h"
+#include "ns3/wifi-mode.h"
+namespace ns3 {
+namespace dot11s {
+uint32_t
+AirtimeLinkMetricCalculator::CalculateMetric(Mac48Address peerAddress, Ptr<MeshWifiInterfaceMac> mac)
+{
+ WifiRemoteStation * station = mac->GetStationManager ()->Lookup(peerAddress);
+ NS_ASSERT(station != 0);
+ Ptr<Packet> test_frame = Create<Packet> (test_length);
+ uint32_t rate = station->GetDataMode(test_frame, test_length+header_length).GetDataRate ();
+ uint32_t payload_nanosec = (uint32_t) ((double) (test_length * 8) * 1e9 / ((double)rate));
+ uint32_t metric = (uint32_t) (((double) (payload_nanosec + overhead_nanosec)) / 102.4 * (station->GetAvgSlrc () + 1));
+ return metric;
+}
+} //namespace dot11s
+} //namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/airtime-metric.h Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,44 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#ifndef AIRTIME_METRIC_H
+#define AIRTIME_METRIC_H
+#include "ns3/mesh-wifi-interface-mac.h"
+namespace ns3 {
+namespace dot11s {
+class AirtimeLinkMetricCalculator : public RefCountBase
+{
+ public:
+ friend class MeshWifiInterfaceMac;
+ uint32_t CalculateMetric(Mac48Address peerAddress, Ptr<MeshWifiInterfaceMac> mac);
+ private:
+ ///\Microseconds of overhead:
+ static const uint32_t overhead_nanosec =
+ (34 //DIFS
+ +9*2 //SIFS
+ +16*2 //Preamble
+ +24) //Ack
+ *1000; //nanoseconds
+ static const uint32_t test_length = 1024;
+ static const uint32_t header_length = 36;
+};
+} //namespace dot11s
+} //namespace ns3
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/dot11s-helper.cc Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,162 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ * Pavel Boyko <boyko@iitp.ru>
+ */
+
+
+#include "dot11s-helper.h"
+
+#include "ns3/mesh-point-device.h"
+#include "ns3/wifi-net-device.h"
+#include "ns3/wifi-phy.h"
+#include "ns3/wifi-channel.h"
+#include "ns3/wifi-remote-station-manager.h"
+#include "ns3/mesh-wifi-interface-mac.h"
+#include "ns3/aarf-wifi-manager.h"
+#include "airtime-metric.h"
+
+namespace ns3 {
+namespace dot11s {
+
+MeshWifiHelper::MeshWifiHelper () :
+ m_ssid("mesh"),
+ m_randomStartDelay (Seconds (0)),
+ m_spreadInterfaceChannels (false)
+{
+}
+
+void
+MeshWifiHelper::SetSsid (Ssid const & s)
+{
+ m_ssid = s;
+}
+
+Ssid MeshWifiHelper::GetSsid () const
+{
+ return m_ssid;
+}
+
+void
+MeshWifiHelper::SetRandomStartDelay (Time t)
+{
+ m_randomStartDelay = t;
+}
+
+void
+MeshWifiHelper::SetSpreadInterfaceChannels (bool s)
+{
+ m_spreadInterfaceChannels = s;
+}
+
+
+Ptr<WifiNetDevice>
+MeshWifiHelper::CreateInterface (const WifiPhyHelper &phyHelper, Ptr<Node> node) const
+{
+ Ptr<WifiNetDevice> device = CreateObject<WifiNetDevice> ();
+
+ // Creating MAC for this interface
+ Ptr<MeshWifiInterfaceMac> mac = CreateObject<MeshWifiInterfaceMac> ();
+ mac->SetSsid (m_ssid);
+ if (m_randomStartDelay > Seconds (0))
+ mac->SetRandomStartDelay (m_randomStartDelay);
+ Ptr<WifiRemoteStationManager> manager = CreateObject<AarfWifiManager> ();
+ Ptr<WifiPhy> phy = phyHelper.Create (node, device);
+ mac->SetAddress (Mac48Address::Allocate ());
+ device->SetMac (mac);
+ device->SetPhy (phy);
+ device->SetRemoteStationManager (manager);
+ Ptr<AirtimeLinkMetricCalculator> metric = Create <AirtimeLinkMetricCalculator> ();
+ mac->SetLinkMetricCallback (MakeCallback(&AirtimeLinkMetricCalculator::CalculateMetric, metric));
+ /*
+ if (channel > 0)
+ mac->SwitchFrequencyChannel (channel);
+ */
+ return device;
+}
+
+NetDeviceContainer
+MeshWifiHelper::Install (const WifiPhyHelper &phyHelper, NodeContainer c, std::vector<uint32_t> roots, uint32_t nInterfaces) const
+{
+ NetDeviceContainer devices;
+ uint32_t node_index = 0;
+ for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i)
+ {
+ Ptr<Node> node = *i;
+
+ // Create a mesh point device
+ Ptr<MeshPointDevice> mp = CreateObject<MeshPointDevice> ();
+ node->AddDevice (mp);
+
+ // Create wifi interfaces (single interface by default)
+ for (uint32_t i = 0; i < nInterfaces; ++i)
+ {
+ Ptr<WifiNetDevice> iface = CreateInterface (phyHelper, node);
+
+ node->AddDevice (iface);
+ mp->AddInterface (iface);
+ }
+
+ // Set different channels on different ifaces
+ if (m_spreadInterfaceChannels)
+ {
+ std::vector<Ptr<NetDevice> > ifaces = mp->GetInterfaces ();
+ for (size_t i = 0; i < ifaces.size(); ++i)
+ {
+ uint32_t channel = i * 5;
+
+ Ptr<WifiNetDevice> iface = ifaces[i]->GetObject<WifiNetDevice> ();
+ NS_ASSERT (iface);
+ Ptr<MeshWifiInterfaceMac> mac = iface->GetMac ()->GetObject<MeshWifiInterfaceMac> ();
+ NS_ASSERT (mac);
+
+ mac->SwitchFrequencyChannel (channel);
+ }
+ }
+
+ // Install 802.11s protocols
+ Ptr<PeerManagementProtocol> pmp = CreateObject<PeerManagementProtocol> ();
+ bool install_ok = pmp->Install (mp);
+ NS_ASSERT (install_ok);
+
+ Ptr<HwmpProtocol> hwmp = CreateObject<HwmpProtocol> ();
+ install_ok = hwmp->Install (mp);
+ NS_ASSERT (install_ok);
+
+ pmp->SetPeerLinkStatusCallback(MakeCallback(&HwmpProtocol::PeerLinkStatus, hwmp));
+ hwmp->SetNeighboursCallback(MakeCallback(&PeerManagementProtocol::GetActiveLinks, pmp));
+ // Setting root mesh point
+ for(std::vector<uint32_t>::const_iterator root_iterator = roots.begin (); root_iterator != roots.end (); root_iterator ++)
+ //if(*root_iterator == i.GetDistanceFrom(c.Begin ()))
+ if(*root_iterator == node_index)
+ hwmp->SetRoot ();
+ devices.Add (mp);
+ node_index ++;
+ }
+ return devices;
+}
+
+NetDeviceContainer
+MeshWifiHelper::Install (const WifiPhyHelper &phy, Ptr<Node> node, std::vector<uint32_t> roots, uint32_t nInterfaces) const
+{
+ return Install (phy, NodeContainer (node), roots, nInterfaces);
+}
+
+} // namespace dot11s
+} //namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/dot11s-helper.h Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,96 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ * Pavel Boyko <boyko@iitp.ru>
+ */
+
+
+#ifndef _MESHWIFIHELPER_H
+#define _MESHWIFIHELPER_H
+
+#include "ns3/wifi-helper.h"
+#include "ns3/ssid.h"
+#include "ns3/nstime.h"
+#include "ns3/peer-management-protocol.h"
+#include "ns3/hwmp-protocol.h"
+
+namespace ns3 {
+namespace dot11s {
+
+class WifiChannel;
+
+/**
+ * \ingroup dot11s
+ *
+ * \brief Helper to create IEEE 802.11s mesh networks
+ */
+class MeshWifiHelper
+{
+public:
+ MeshWifiHelper ();
+ /// Set mesh SSID
+ void SetSsid (const Ssid &);
+ /// Get mesh SSID
+ Ssid GetSsid () const;
+ /// Set maximum random start delay
+ void SetRandomStartDelay (Time delay);
+ /**
+ * \brief Spread/not spread frequency channels of MP interfaces.
+ *
+ * If set to true different non-overlaping 20MHz frequency
+ * channels will be assigned to different mesh point interfaces.
+ */
+ void SetSpreadInterfaceChannels (bool);
+
+ /**
+ * \brief Install 802.11s mesh device & protocols on given node
+ *
+ * \param phy Wifi PHY helper
+ * \param nodes List of nodes to install
+ * \param roots List of root mesh points
+ * \param nInterfaces Number of mesh point radio interfaces (= WiFi NICs)
+ *
+ * \return list of created mesh point devices, see MeshPointDevice
+ */
+ NetDeviceContainer Install (const WifiPhyHelper &phyHelper, NodeContainer c, std::vector<uint32_t> roots = std::vector<uint32_t> (), uint32_t nInterfaces = 1) const;
+ /**
+ * \brief Install 802.11s mesh device & protocols on given node
+ *
+ * \param phy Wifi PHY helper
+ * \param node Node to install
+ * \param roots List of root mesh points
+ * \param nInterfaces Number of mesh point radio interfaces (= WiFi NICs)
+ *
+ * \return list of created mesh point devices, see MeshPointDevice
+ */
+ NetDeviceContainer Install (const WifiPhyHelper &phy, Ptr<Node> node, std::vector<uint32_t> roots = std::vector<uint32_t> (), uint32_t nInterfaces = 1) const;
+
+private:
+ Ssid m_ssid;
+ Time m_randomStartDelay;
+ bool m_spreadInterfaceChannels;
+
+ /// Create single mesh interface NIC
+ Ptr<WifiNetDevice> CreateInterface (const WifiPhyHelper &phyHelper, Ptr<Node> node) const;
+
+};
+} // namespace dot11s
+} //namespace ns3
+
+#endif /* _MESHWIFIHELPER_H */
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/dot11s-mac-header.cc Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,381 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#include "ns3/assert.h"
+#include "ns3/address-utils.h"
+#include "dot11s-mac-header.h"
+#include "ns3/packet.h"
+#include "ns3/test.h"
+
+namespace ns3 {
+namespace dot11s {
+/***********************************************************
+ * Here Mesh Mac Header functionality is defined.
+ ***********************************************************/
+TypeId
+Dot11sMacHeader::GetTypeId ()
+{
+ static TypeId tid = TypeId ("ns3::Dot11sMacHeader")
+ .SetParent<Header> ()
+ .AddConstructor<Dot11sMacHeader> ()
+ ;
+ return tid;
+}
+Dot11sMacHeader::Dot11sMacHeader ():
+ m_meshFlags (0),
+ m_meshTtl (0),
+ m_meshSeqno (0),
+ m_addr4 (Mac48Address ()),
+ m_addr5 (Mac48Address ()),
+ m_addr6 (Mac48Address ())
+{
+}
+Dot11sMacHeader::~Dot11sMacHeader ()
+{
+}
+TypeId
+Dot11sMacHeader::GetInstanceTypeId () const
+{
+ return GetTypeId ();
+}
+void
+Dot11sMacHeader::SetAddr4 (Mac48Address address)
+{
+ m_addr4 = address;
+}
+void
+Dot11sMacHeader::SetAddr5 (Mac48Address address)
+{
+ m_addr5 = address;
+}
+void
+Dot11sMacHeader::SetAddr6 (Mac48Address address)
+{
+ m_addr6 = address;
+}
+Mac48Address
+Dot11sMacHeader::GetAddr4 () const
+{
+ return m_addr4;
+}
+Mac48Address
+Dot11sMacHeader::GetAddr5 () const
+{
+ return m_addr5;
+}
+Mac48Address
+Dot11sMacHeader::GetAddr6 () const
+{
+ return m_addr6;
+}
+void
+Dot11sMacHeader::SetMeshSeqno (uint32_t seqno)
+{
+ m_meshSeqno = seqno;
+}
+uint32_t
+Dot11sMacHeader::GetMeshSeqno () const
+{
+ return m_meshSeqno;
+}
+void
+Dot11sMacHeader::SetMeshTtl (uint8_t TTL)
+{
+ m_meshTtl = TTL;
+}
+uint8_t
+Dot11sMacHeader::GetMeshTtl () const
+{
+ return m_meshTtl;
+}
+void
+Dot11sMacHeader::SetAddressExt (uint8_t num_of_addresses)
+{
+ if (num_of_addresses > 3)
+ return;
+ m_meshFlags |= 0xc0 & (num_of_addresses << 6);
+}
+uint8_t
+Dot11sMacHeader::GetAddressExt () const
+{
+ return ((0xc0 & m_meshFlags) >> 6);
+}
+uint32_t
+Dot11sMacHeader::GetSerializedSize () const
+{
+ return 6 + GetAddressExt () * 6;
+}
+void
+Dot11sMacHeader::Serialize (Buffer::Iterator start) const
+{
+ Buffer::Iterator i = start;
+ i.WriteU8 (m_meshFlags);
+ i.WriteU8 (m_meshTtl);
+ i.WriteU32 (m_meshSeqno);
+ uint8_t addresses_to_add = GetAddressExt ();
+ //Writing Address extensions:
+ if ((addresses_to_add == 1) || (addresses_to_add == 3))
+ WriteTo (i, m_addr4);
+ if (addresses_to_add > 1)
+ WriteTo (i, m_addr5);
+ if (addresses_to_add > 1)
+ WriteTo (i, m_addr6);
+}
+uint32_t
+Dot11sMacHeader::Deserialize (Buffer::Iterator start)
+{
+ Buffer::Iterator i = start;
+ uint8_t addresses_to_read = 0;
+ m_meshFlags = i.ReadU8 ();
+ m_meshTtl = i.ReadU8 ();
+ m_meshSeqno = i.ReadU32 ();
+ addresses_to_read = (m_meshFlags & 0xc0) >> 6;
+ if ((addresses_to_read == 1) || (addresses_to_read == 3))
+ ReadFrom (i, m_addr4);
+ if (addresses_to_read > 1)
+ ReadFrom (i, m_addr5);
+ if (addresses_to_read > 1)
+ ReadFrom (i, m_addr6);
+ return i.GetDistanceFrom (start);
+}
+void
+Dot11sMacHeader::Print (std::ostream &os) const
+{
+ os << "flags = " << (uint16_t)m_meshFlags
+ << "\nttl = " << (uint16_t)m_meshTtl
+ << "\nseqno = " << m_meshSeqno
+ << "\naddr4 = " << m_addr4
+ << "\naddr5 = " << m_addr5
+ << "\naddr6 = " << m_addr6;
+}
+bool operator== (const Dot11sMacHeader & a, const Dot11sMacHeader & b)
+{
+ return (
+ (a.m_meshFlags == b.m_meshFlags) &&
+ (a.m_meshTtl == b.m_meshTtl) &&
+ (a.m_meshSeqno == b.m_meshSeqno) &&
+ (a.m_addr4 == b.m_addr4) &&
+ (a.m_addr5 == b.m_addr5) &&
+ (a.m_addr6 == b.m_addr6)
+ );
+}
+/**********************************************************
+ * MultihopActionFrame
+ **********************************************************/
+WifiMeshMultihopActionHeader::WifiMeshMultihopActionHeader ()
+{
+}
+WifiMeshMultihopActionHeader::~WifiMeshMultihopActionHeader ()
+{
+}
+void
+WifiMeshMultihopActionHeader::SetAction (
+ WifiMeshMultihopActionHeader::CategoryValue type,
+ WifiMeshMultihopActionHeader::ActionValue action)
+{
+ m_category = type;
+
+ switch (type)
+ {
+ case MESH_PEER_LINK_MGT:
+ {
+ m_actionValue = action.peerLink;
+ break;
+ }
+ case MESH_PATH_SELECTION:
+ {
+ m_actionValue = action.pathSelection;
+ break;
+ }
+ case MESH_LINK_METRIC:
+ case MESH_INTERWORK_ACTION:
+ case MESH_RESOURCE_COORDINATION:
+ break;
+ };
+}
+WifiMeshMultihopActionHeader::CategoryValue
+WifiMeshMultihopActionHeader::GetCategory ()
+{
+ switch (m_category)
+ {
+ case MESH_PEER_LINK_MGT:
+ return MESH_PEER_LINK_MGT;
+ case MESH_LINK_METRIC:
+ return MESH_LINK_METRIC;
+ case MESH_PATH_SELECTION:
+ return MESH_PATH_SELECTION;
+ case MESH_INTERWORK_ACTION:
+ return MESH_INTERWORK_ACTION;
+ case MESH_RESOURCE_COORDINATION:
+ return MESH_RESOURCE_COORDINATION;
+ default:
+ NS_ASSERT (false);
+ return MESH_PEER_LINK_MGT;
+ }
+}
+WifiMeshMultihopActionHeader::ActionValue
+WifiMeshMultihopActionHeader::GetAction ()
+{
+ ActionValue retval;
+ switch (m_category)
+ {
+ case MESH_PEER_LINK_MGT:
+ switch (m_actionValue)
+ {
+ case PEER_LINK_OPEN:
+ retval.peerLink = PEER_LINK_OPEN;
+ return retval;
+ case PEER_LINK_CONFIRM:
+ retval.peerLink = PEER_LINK_CONFIRM;
+ return retval;
+ case PEER_LINK_CLOSE:
+ retval.peerLink = PEER_LINK_CLOSE;
+ return retval;
+ default:
+ NS_ASSERT (false);
+ return retval;
+ }
+ case MESH_PATH_SELECTION:
+ switch (m_actionValue)
+ {
+ case PATH_REQUEST:
+ retval.pathSelection = PATH_REQUEST;
+ return retval;
+ case PATH_REPLY:
+ retval.pathSelection = PATH_REPLY;
+ return retval;
+ case PATH_ERROR:
+ retval.pathSelection = PATH_ERROR;
+ return retval;
+ case ROOT_ANNOUNCEMENT:
+ retval.pathSelection = ROOT_ANNOUNCEMENT;
+ return retval;
+ default:
+ NS_ASSERT (false);
+ return retval;
+ }
+ case MESH_LINK_METRIC:
+ // ???
+ case MESH_INTERWORK_ACTION:
+ // ???
+ case MESH_RESOURCE_COORDINATION:
+ // ???
+ default:
+ NS_ASSERT (false);
+ return retval;
+ }
+}
+TypeId
+WifiMeshMultihopActionHeader::GetTypeId ()
+{
+ static TypeId tid = TypeId ("ns3::WifiMeshMultihopActionHeader")
+ .SetParent<Header> ()
+ .AddConstructor<WifiMeshMultihopActionHeader> ()
+ ;
+ return tid;
+}
+TypeId
+WifiMeshMultihopActionHeader::GetInstanceTypeId () const
+{
+ return GetTypeId ();
+}
+void
+WifiMeshMultihopActionHeader::Print (std::ostream &os) const
+{
+}
+uint32_t
+WifiMeshMultihopActionHeader::GetSerializedSize () const
+{
+ return 2;
+}
+void
+WifiMeshMultihopActionHeader::Serialize (Buffer::Iterator start) const
+{
+ start.WriteU8 (m_category);
+ start.WriteU8 (m_actionValue);
+}
+uint32_t
+WifiMeshMultihopActionHeader::Deserialize (Buffer::Iterator start)
+{
+ Buffer::Iterator i = start;
+ m_category = i.ReadU8 ();
+ m_actionValue = i.ReadU8 ();
+ return i.GetDistanceFrom (start);
+}
+#ifdef RUN_SELF_TESTS
+
+/// Built-in self test for Dot11sMacHeader
+struct Dot11sMacHeaderBist : public Test
+{
+ Dot11sMacHeaderBist () : Test ("Mesh/802.11s/IE/Dot11sMacHeader") {}
+ virtual bool RunTests();
+};
+
+/// Test instance
+static Dot11sMacHeaderBist g_Dot11sMacHeaderBist;
+
+bool Dot11sMacHeaderBist::RunTests ()
+{
+ bool result (true);
+ {
+ Dot11sMacHeader a;
+ a.SetAddressExt(3);
+ a.SetAddr4(Mac48Address ("11:22:33:44:55:66"));
+ a.SetAddr5(Mac48Address ("11:00:33:00:55:00"));
+ a.SetAddr6(Mac48Address ("00:22:00:44:00:66"));
+ a.SetMeshTtl (122);
+ a.SetMeshSeqno (321);
+ Ptr<Packet> packet = Create<Packet> ();
+ packet->AddHeader (a);
+ Dot11sMacHeader b;
+ packet->RemoveHeader (b);
+ NS_TEST_ASSERT_EQUAL (a, b);
+ }
+ {
+ Dot11sMacHeader a;
+ a.SetAddressExt(2);
+ a.SetAddr5(Mac48Address ("11:00:33:00:55:00"));
+ a.SetAddr6(Mac48Address ("00:22:00:44:00:66"));
+ a.SetMeshTtl (122);
+ a.SetMeshSeqno (321);
+ Ptr<Packet> packet = Create<Packet> ();
+ packet->AddHeader (a);
+ Dot11sMacHeader b;
+ packet->RemoveHeader (b);
+ NS_TEST_ASSERT_EQUAL (a, b);
+ }
+ {
+ Dot11sMacHeader a;
+ a.SetAddressExt(1);
+ a.SetAddr4(Mac48Address ("11:22:33:44:55:66"));
+ a.SetMeshTtl (122);
+ a.SetMeshSeqno (321);
+ Ptr<Packet> packet = Create<Packet> ();
+ packet->AddHeader (a);
+ Dot11sMacHeader b;
+ packet->RemoveHeader (b);
+ NS_TEST_ASSERT_EQUAL (a, b);
+ }
+ return result;
+}
+#endif
+} //namespace dot11s
+} // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/dot11s-mac-header.h Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,163 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#ifndef MESH_WIFI_MAC_HEADER_H
+#define MESH_WIFI_MAC_HEADER_H
+
+#include "ns3/header.h"
+#include "ns3/mac48-address.h"
+
+namespace ns3 {
+namespace dot11s {
+/**
+ * \ingroup dot11s
+ *
+ * \brief See IEEE 802.11s draft 3.0 section 7.1.3.5b
+ */
+class Dot11sMacHeader : public Header
+{
+public:
+ Dot11sMacHeader ();
+ ~Dot11sMacHeader ();
+ static TypeId GetTypeId ();
+ virtual TypeId GetInstanceTypeId () const;
+ virtual void Print (std::ostream &os) const;
+
+ void SetAddr4 (Mac48Address address);
+ void SetAddr5 (Mac48Address address);
+ void SetAddr6 (Mac48Address address);
+ Mac48Address GetAddr4 () const;
+ Mac48Address GetAddr5 () const;
+ Mac48Address GetAddr6 () const;
+
+ void SetMeshSeqno (uint32_t seqno);
+ uint32_t GetMeshSeqno () const;
+
+ void SetMeshTtl (uint8_t TTL);
+ uint8_t GetMeshTtl () const;
+
+ void SetAddressExt (uint8_t num_of_addresses);
+ uint8_t GetAddressExt () const;
+
+ virtual uint32_t GetSerializedSize () const;
+ virtual void Serialize (Buffer::Iterator start) const;
+ virtual uint32_t Deserialize (Buffer::Iterator start);
+private:
+ uint8_t m_meshFlags;
+ uint8_t m_meshTtl;
+ uint32_t m_meshSeqno;
+ Mac48Address m_addr4;
+ Mac48Address m_addr5;
+ Mac48Address m_addr6;
+ friend bool operator== (const Dot11sMacHeader & a, const Dot11sMacHeader & b);
+};
+bool operator== (const Dot11sMacHeader & a, const Dot11sMacHeader & b);
+
+/**
+ * \ingroup dot11s
+ *
+ * \brief See IEEE 802.11s draft 3.0 section 7.2.3.14
+ *
+ * Multichop action frame consists of Mesh header, Action, and
+ * the last information. Mesh header is present within all data
+ * frames and multihop action frames, so Mesh header is a
+ * separate structure. Each MultihopAction frames (frames like
+ * PREQ, PREP and other) start form Category field and Action
+ * value field, so the Multihop Action Frame should containt
+ * three fields: Category, Action Value.
+ */
+class WifiMeshMultihopActionHeader : public Header
+{
+public:
+ WifiMeshMultihopActionHeader ();
+ ~WifiMeshMultihopActionHeader ();
+
+ /* Compatible with open80211s implementation */
+ enum CategoryValue //table 7-24 staring from 4
+ {
+ MESH_PEER_LINK_MGT = 30,
+ MESH_LINK_METRIC = 31,
+ MESH_PATH_SELECTION = 32,
+ MESH_INTERWORK_ACTION = 33,
+ MESH_RESOURCE_COORDINATION = 34,
+ };
+ /* Compatible with open80211s implementation */
+ enum PeerLinkMgtActionValue
+ {
+ PEER_LINK_OPEN = 0,
+ PEER_LINK_CONFIRM = 1,
+ PEER_LINK_CLOSE = 2,
+ };
+ enum LinkMetricActionValue
+ {
+ LINK_METRIC_REQUEST = 0,
+ LINK_METRIC_REPORT,
+ };
+ /* Compatible with open80211s implementation */
+ enum PathSelectionActionValue
+ {
+ PATH_REQUEST = 0,
+ PATH_REPLY = 1,
+ PATH_ERROR = 2,
+ ROOT_ANNOUNCEMENT = 3,
+ };
+ enum InterworkActionValue
+ {
+ PORTAL_ANNOUNCEMENT = 0,
+ };
+ enum ResourceCoordinationActionValue
+ {
+ CONGESTION_CONTROL_NOTIFICATION = 0,
+ MDA_SETUP_REQUEST,
+ MDA_SETUP_REPLY,
+ MDAOP_ADVERTISMENT_REQUEST,
+ MDAOP_ADVERTISMENTS,
+ MDAOP_SET_TEARDOWN,
+ BEACON_TIMING_REQUEST,
+ BEACON_TIMING_RESPONSE,
+ TBTT_ADJASTMENT_REQUEST,
+ MESH_CHANNEL_SWITCH_ANNOUNCEMENT,
+ };
+ typedef union
+ {
+ enum PeerLinkMgtActionValue peerLink;
+ enum LinkMetricActionValue linkMetrtic;
+ enum PathSelectionActionValue pathSelection;
+ enum InterworkActionValue interwork;
+ enum ResourceCoordinationActionValue resourceCoordination;
+ } ActionValue;
+ void SetAction (enum CategoryValue type,ActionValue action);
+
+ CategoryValue GetCategory ();
+ ActionValue GetAction ();
+ static TypeId GetTypeId ();
+ virtual TypeId GetInstanceTypeId () const;
+ virtual void Print (std::ostream &os) const;
+ virtual uint32_t GetSerializedSize () const;
+ virtual void Serialize (Buffer::Iterator start) const;
+ virtual uint32_t Deserialize (Buffer::Iterator start);
+private:
+ uint8_t m_category;
+ uint8_t m_actionValue;
+};
+} //namespace dot11s
+} // namespace ns3
+#endif /* MESH_WIFI_MAC_HEADER_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/dot11s.h Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,34 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Pavel Boyko <boyko@iitp.ru>
+ *
+ * This is doxygen module description, don't include
+ */
+/**
+ * \ingroup mesh
+ * \defgroup dot11s IEEE 802.11s draft
+ *
+ * \brief IEEE 802.11s (mesh) draft standard implementation
+ *
+ * Current model conforms IEEE 802.11s D3.0 draft version and includes
+ * Peer Management Protocol and HWMP (routing) Protocol implementations.
+ *
+ * The multi-interface (aka multi radio) mesh points are supported as an
+ * extensions of ieee draft version 3.0. Note that corresponding helper
+ * creates single interface station by default.
+ */
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/hwmp-mac-plugin.cc Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,329 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#include "ns3/mesh-wifi-interface-mac.h"
+#include "ns3/packet.h"
+#include "ns3/simulator.h"
+#include "ns3/nstime.h"
+#include "ns3/log.h"
+#include "hwmp-mac-plugin.h"
+#include "dot11s-mac-header.h"
+#include "hwmp-protocol.h"
+#include "hwmp-tag.h"
+#include "ie-dot11s-preq.h"
+#include "ie-dot11s-prep.h"
+
+namespace ns3 {
+namespace dot11s {
+
+NS_LOG_COMPONENT_DEFINE ("HwmpMacPlugin");
+HwmpMacPlugin::HwmpMacPlugin (uint32_t ifIndex, Ptr<HwmpProtocol> protocol):
+ m_ifIndex (ifIndex),
+ m_protocol (protocol)
+{
+}
+HwmpMacPlugin::~HwmpMacPlugin ()
+{
+}
+void
+HwmpMacPlugin::SetParent (Ptr<MeshWifiInterfaceMac> parent)
+{
+ m_parent = parent;
+}
+bool
+HwmpMacPlugin::Receive (Ptr<Packet> packet, const WifiMacHeader & header)
+{
+ //TODO: here we fix only mesh header
+ if(header.IsData())
+ {
+ Dot11sMacHeader meshHdr;
+ HwmpTag tag;
+ if(packet->PeekPacketTag (tag))
+ {
+ NS_ASSERT (false);
+ }
+ packet->RemoveHeader(meshHdr);
+ //TODO: address extension
+ Mac48Address destination;
+ switch (meshHdr.GetAddressExt ())
+ {
+ case 0:
+ destination = header.GetAddr3 ();
+ break;
+ default:
+ NS_ASSERT(false);
+ };
+ tag.SetSeqno (meshHdr.GetMeshSeqno ());
+ if(meshHdr.GetMeshTtl () == 0)
+ {
+ NS_ASSERT(false);
+ return false;
+ }
+ tag.SetTtl (meshHdr.GetMeshTtl () - 1);
+ if(m_protocol->GetAddress() != destination)
+ packet->AddPacketTag(tag);
+ if (destination == Mac48Address::GetBroadcast ())
+ if(m_protocol->DropDataFrame (meshHdr.GetMeshSeqno (), header.GetAddr4 ()) )
+ return false;
+ }
+ if(header.IsAction())
+ {
+ // TODO don't use multihop header
+ Dot11sMacHeader meshHdr;
+ packet->RemoveHeader (meshHdr);
+ //parse multihop action header:
+ WifiMeshMultihopActionHeader multihopHdr;
+ packet->RemoveHeader (multihopHdr);
+ WifiMeshMultihopActionHeader::ActionValue actionValue = multihopHdr.GetAction ();
+ if(multihopHdr.GetCategory () != WifiMeshMultihopActionHeader::MESH_PATH_SELECTION)
+ return true;
+ if(meshHdr.GetMeshTtl () == 0)
+ return false;
+ switch (actionValue.pathSelection)
+ {
+ case WifiMeshMultihopActionHeader::PATH_REQUEST:
+ {
+ IePreq preq;
+ packet->RemoveHeader (preq);
+ if(preq.GetOriginatorAddress () == m_protocol->GetAddress ())
+ return false;
+ if (preq.GetTtl () == 0)
+ return false;
+ preq.DecrementTtl ();
+ m_protocol->ReceivePreq (preq, header.GetAddr2 (), m_ifIndex, m_parent->GetLinkMetric(header.GetAddr2 ()));
+ return false;
+ }
+ case WifiMeshMultihopActionHeader::PATH_REPLY:
+ {
+ IePrep prep;
+ packet->RemoveHeader (prep);
+ if(prep.GetTtl () == 0)
+ return false;
+ prep.DecrementTtl ();
+ m_protocol->ReceivePrep (prep, header.GetAddr2 (), m_ifIndex, m_parent->GetLinkMetric(header.GetAddr2 ()));
+ return false;
+ }
+ case WifiMeshMultihopActionHeader::PATH_ERROR:
+ {
+ IePerr perr;
+ packet->RemoveHeader (perr);
+ m_protocol->ReceivePerr (perr, header.GetAddr2 (), m_ifIndex);
+ return false;
+ }
+ case WifiMeshMultihopActionHeader::ROOT_ANNOUNCEMENT:
+ return false;
+ }
+ }
+ return true;
+}
+bool
+HwmpMacPlugin::UpdateOutcomingFrame (Ptr<Packet> packet, WifiMacHeader & header, Mac48Address from, Mac48Address to) const
+{
+ //TODO: add a mesh header and remove a TAG
+ NS_ASSERT(header.IsData ());
+ HwmpTag tag;
+ bool tagExists = packet->RemovePacketTag(tag);
+ if (!tagExists)
+ {
+ NS_ASSERT (false);
+ }
+ Dot11sMacHeader meshHdr;
+ meshHdr.SetMeshSeqno(tag.GetSeqno());
+ meshHdr.SetMeshTtl(tag.GetTtl());
+ packet->AddHeader(meshHdr);
+ header.SetAddr1(tag.GetAddress());
+ return true;
+}
+void
+HwmpMacPlugin::SendPreq(IePreq preq)
+{
+ m_preqQueue.push_back (preq);
+ SendOnePreq ();
+}
+void
+HwmpMacPlugin::RequestDestination (Mac48Address dst, uint32_t originator_seqno, uint32_t dst_seqno)
+{
+ for(std::vector<IePreq>::iterator i = m_preqQueue.begin (); i != m_preqQueue.end (); i ++)
+ if(i->MayAddAddress(m_protocol->GetAddress ()))
+ {
+ i->AddDestinationAddressElement (m_protocol->GetDoFlag(), m_protocol->GetRfFlag(), dst, dst_seqno);
+ return;
+ }
+ IePreq preq;
+ //fill PREQ:
+ preq.SetHopcount (0);
+ preq.SetTTL (m_protocol->GetMaxTtl ());
+ preq.SetPreqID (m_protocol->GetNextPreqId ());
+ preq.SetOriginatorAddress (m_protocol->GetAddress ());
+ preq.SetOriginatorSeqNumber (originator_seqno);
+ preq.SetLifetime (m_protocol->GetActivePathLifetime ());
+ preq.AddDestinationAddressElement (false, false, dst, dst_seqno);
+ m_preqQueue.push_back (preq);
+ //set iterator position to my preq:
+ SendOnePreq ();
+}
+void
+HwmpMacPlugin::SendOnePreq ()
+{
+ if(m_preqTimer.IsRunning ())
+ return;
+ if (m_preqQueue.size () == 0)
+ return;
+ //reschedule sending PREQ
+ NS_ASSERT (!m_preqTimer.IsRunning());
+ m_preqTimer = Simulator::Schedule (m_protocol->GetPreqMinInterval (), &HwmpMacPlugin::SendOnePreq, this);
+ Ptr<Packet> packet = Create<Packet> ();
+ packet->AddHeader(m_preqQueue[0]);
+ //Multihop action header:
+ WifiMeshMultihopActionHeader multihopHdr;
+ WifiMeshMultihopActionHeader::ActionValue action;
+ action.pathSelection = WifiMeshMultihopActionHeader::PATH_REQUEST;
+ multihopHdr.SetAction (WifiMeshMultihopActionHeader::MESH_PATH_SELECTION, action);
+ packet->AddHeader (multihopHdr);
+ //Mesh header
+ Dot11sMacHeader meshHdr;
+ meshHdr.SetMeshTtl (m_protocol->GetMaxTtl ());
+ //TODO: should seqno be here?
+ meshHdr.SetMeshSeqno (0);
+ meshHdr.SetAddressExt(1);
+ meshHdr.SetAddr4(m_preqQueue[0].GetOriginatorAddress ());
+ packet->AddHeader (meshHdr);
+ //create 802.11 header:
+ // TODO don't use me
+ WifiMacHeader hdr;
+ hdr.SetAction ();
+ hdr.SetDsNotFrom ();
+ hdr.SetDsNotTo ();
+ hdr.SetAddr2 (m_parent->GetAddress ());
+ hdr.SetAddr3 (Mac48Address::GetBroadcast ());
+ //Send Management frame
+ std::vector <Mac48Address> receivers = m_protocol->GetPreqReceivers (m_ifIndex);
+ for(std::vector<Mac48Address>::const_iterator i = receivers.begin (); i != receivers.end (); i ++)
+ {
+ hdr.SetAddr1 (*i);
+ m_parent->SendManagementFrame(packet, hdr);
+ }
+ //erase queue
+ m_preqQueue.erase (m_preqQueue.begin());
+}
+void
+HwmpMacPlugin::SendOnePerr()
+{
+ if(m_perrTimer.IsRunning ())
+ return;
+ if(m_myPerr.receivers.size () >= m_protocol->GetUnicastPerrThreshold ())
+ {
+ m_myPerr.receivers.clear ();
+ m_myPerr.receivers.push_back (Mac48Address::GetBroadcast ());
+ }
+ m_perrTimer = Simulator::Schedule (m_protocol->GetPerrMinInterval (), &HwmpMacPlugin::SendOnePerr, this);
+//Create packet
+ Ptr<Packet> packet = Create<Packet> ();
+ packet->AddHeader(m_myPerr.perr);
+ //Multihop action header:
+ WifiMeshMultihopActionHeader multihopHdr;
+ WifiMeshMultihopActionHeader::ActionValue action;
+ action.pathSelection = WifiMeshMultihopActionHeader::PATH_ERROR;
+ multihopHdr.SetAction (WifiMeshMultihopActionHeader::MESH_PATH_SELECTION, action);
+ packet->AddHeader (multihopHdr);
+ //Mesh header
+ Dot11sMacHeader meshHdr;
+ meshHdr.SetMeshTtl (m_protocol->GetMaxTtl ());
+ //TODO: should seqno be here?
+ meshHdr.SetMeshSeqno (0);
+ meshHdr.SetAddressExt(1);
+ meshHdr.SetAddr4(m_protocol->GetAddress ());
+ packet->AddHeader (meshHdr);
+ //create 802.11 header:
+ // TODO don't use me
+ WifiMacHeader hdr;
+ hdr.SetAction ();
+ hdr.SetDsNotFrom ();
+ hdr.SetDsNotTo ();
+ hdr.SetAddr2 (m_parent->GetAddress ());
+ hdr.SetAddr3 (Mac48Address::GetBroadcast ());
+ //Send Management frame
+ for(std::vector<Mac48Address>::const_iterator i = m_myPerr.receivers.begin (); i != m_myPerr.receivers.end (); i ++)
+ {
+ hdr.SetAddr1 (*i);
+ m_parent->SendManagementFrame(packet, hdr);
+ }
+ m_myPerr.perr.ResetPerr ();
+ m_myPerr.receivers.clear ();
+}
+void
+HwmpMacPlugin::SendPrep (IePrep prep, Mac48Address receiver)
+{
+ //Create packet
+ Ptr<Packet> packet = Create<Packet> ();
+ packet->AddHeader(prep);
+ //Multihop action header:
+ WifiMeshMultihopActionHeader multihopHdr;
+ WifiMeshMultihopActionHeader::ActionValue action;
+ action.pathSelection = WifiMeshMultihopActionHeader::PATH_REPLY;
+ multihopHdr.SetAction (WifiMeshMultihopActionHeader::MESH_PATH_SELECTION, action);
+ packet->AddHeader (multihopHdr);
+ //Mesh header
+ Dot11sMacHeader meshHdr;
+ meshHdr.SetMeshTtl (m_protocol->GetMaxTtl ());
+ //TODO: should seqno be here?
+ meshHdr.SetMeshSeqno (0);
+ meshHdr.SetAddressExt(1);
+ meshHdr.SetAddr4(prep.GetOriginatorAddress ());
+ packet->AddHeader (meshHdr);
+ //create 802.11 header:
+ // TODO don't use me
+ WifiMacHeader hdr;
+ hdr.SetAction ();
+ hdr.SetDsNotFrom ();
+ hdr.SetDsNotTo ();
+ hdr.SetAddr1 (receiver);
+ hdr.SetAddr2 (m_parent->GetAddress ());
+ hdr.SetAddr3 (prep.GetDestinationAddress ());
+ //Send Management frame
+ m_parent->SendManagementFrame(packet, hdr);
+}
+void
+HwmpMacPlugin::SendPerr(IePerr perr, std::vector<Mac48Address> receivers)
+{
+ m_myPerr.perr.Merge(perr);
+ for(unsigned int i = 0; i < receivers.size (); i ++)
+ {
+ bool should_add = true;
+ for (unsigned int j = 0; j < m_myPerr.receivers.size (); j ++)
+ if(receivers[j] == m_myPerr.receivers[i])
+ should_add = false;
+ if(should_add)
+ m_myPerr.receivers.push_back(receivers[i]);
+ }
+ SendOnePerr ();
+}
+uint32_t
+HwmpMacPlugin::GetLinkMetric(Mac48Address peerAddress) const
+{
+ return m_parent->GetLinkMetric(peerAddress);
+}
+uint16_t
+HwmpMacPlugin::GetChannelId () const
+{
+ return m_parent->GetFrequencyChannel ();
+}
+} //namespace dot11s
+}//namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/hwmp-mac-plugin.h Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,103 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#ifndef HWMP_STATE_H
+#define HWMP_STATE_H
+
+#include "ns3/mesh-wifi-interface-mac-plugin.h"
+#include "ie-dot11s-perr.h"
+
+namespace ns3 {
+
+class MeshWifiInterfaceMac;
+
+namespace dot11s {
+
+class HwmpProtocol;
+class IePreq;
+class IePrep;
+class IePerr;
+
+/**
+ * \ingroup dot11s
+ *
+ * \brief Interface MAC plugin for HWMP -- 802.11s routing protocol
+ */
+class HwmpMacPlugin : public MeshWifiInterfaceMacPlugin
+{
+public:
+ HwmpMacPlugin (uint32_t, Ptr<HwmpProtocol>);
+ ~HwmpMacPlugin ();
+ ///\name Inherited from MAC plugin
+ //\{
+ void SetParent (Ptr<MeshWifiInterfaceMac> parent);
+ bool Receive (Ptr<Packet> packet, const WifiMacHeader & header);
+ bool UpdateOutcomingFrame (Ptr<Packet> packet, WifiMacHeader & header, Mac48Address from, Mac48Address to) const;
+ /// Update beacon is empty, because HWMP does not know anything about beacons
+ void UpdateBeacon (MeshWifiBeacon & beacon) const {};
+ //\}
+
+private:
+ friend class HwmpProtocol;
+
+ ///\name Intercation with HWMP:
+ //\{
+ void SendPreq(IePreq preq);
+ void SendPrep(IePrep prep, Mac48Address receiver);
+ void SendPerr(IePerr perr, std::vector<Mac48Address> receivers);
+ ///\brief Request a destination. If can not send preq immediately -
+ //add a destination to exisying PREQ generated by me and stored in
+ //PREQ queue
+ ///\param originator_seqno is a sequence number that shall be preq
+ //originator sequenece number
+ ///\param dst_seqno is a sequence number taken from routing table
+ void RequestDestination (Mac48Address dest, uint32_t originator_seqno, uint32_t dst_seqno);
+ //\}
+
+ /// Sends one PREQ when PreqMinInterval after last PREQ expires (if any PREQ exists in rhe queue)
+ void SendOnePreq ();
+ void SendOnePerr ();
+ /// \return metric to HWMP protocol, needed only by metrics to add
+ //peer as routing entry
+ uint32_t GetLinkMetric (Mac48Address peerAddress) const;
+ uint16_t GetChannelId () const;
+private:
+ Ptr<MeshWifiInterfaceMac> m_parent;
+ uint32_t m_ifIndex;
+ Ptr<HwmpProtocol> m_protocol;
+
+ ///\name PREQ queue and PREQ timer:
+ //\{
+ EventId m_preqTimer;
+ std::vector<IePreq> m_preqQueue;
+ //\}
+ ///\name PERR timer and stored path error
+ //{
+ EventId m_perrTimer;
+ struct MyPerr {
+ IePerr perr;
+ std::vector<Mac48Address> receivers;
+ };
+ MyPerr m_myPerr;
+};
+} //namespace dot11s
+} //namespace ns3
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/hwmp-protocol.cc Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,884 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#include "hwmp-protocol.h"
+#include "hwmp-mac-plugin.h"
+#include "hwmp-tag.h"
+#include "hwmp-rtable.h"
+#include "ns3/log.h"
+#include "ns3/simulator.h"
+#include "ns3/packet.h"
+#include "ns3/mesh-point-device.h"
+#include "ns3/wifi-net-device.h"
+#include "ns3/mesh-point-device.h"
+#include "ns3/mesh-wifi-interface-mac.h"
+#include "ns3/random-variable.h"
+#include "ie-dot11s-preq.h"
+#include "ie-dot11s-prep.h"
+#include "ie-dot11s-perr.h"
+
+NS_LOG_COMPONENT_DEFINE ("HwmpProtocol");
+
+namespace ns3 {
+namespace dot11s {
+
+NS_OBJECT_ENSURE_REGISTERED (HwmpProtocol);
+TypeId
+HwmpProtocol::GetTypeId ()
+{
+ static TypeId tid = TypeId ("ns3::dot11s::HwmpProtocol")
+ .SetParent<MeshL2RoutingProtocol> ()
+ .AddConstructor<HwmpProtocol> ()
+ .AddAttribute ("dot11MeshHWMPmaxPREQretries",
+ "Maximum number of retries before we suppose the destination to be unreachable",
+ UintegerValue (3),
+ MakeUintegerAccessor (&HwmpProtocol::m_dot11MeshHWMPmaxPREQretries),
+ MakeUintegerChecker<uint8_t> (1)
+ )
+ .AddAttribute ("dot11MeshHWMPnetDiameterTraversalTime",
+ "Time we suppose the packet to go from one edge of the network to another",
+ TimeValue (MicroSeconds (1024*100)),
+ MakeTimeAccessor (&HwmpProtocol::m_dot11MeshHWMPnetDiameterTraversalTime),
+ MakeTimeChecker ()
+ )
+ .AddAttribute ("dot11MeshHWMPpreqMinInterval",
+ "Minimal interval between to successive PREQs",
+ TimeValue (MicroSeconds (1024*100)),
+ MakeTimeAccessor (&HwmpProtocol::m_dot11MeshHWMPpreqMinInterval),
+ MakeTimeChecker ()
+ )
+ .AddAttribute ("dot11MeshHWMPperrMinInterval",
+ "Minimal interval between to successive PREQs",
+ TimeValue (MicroSeconds (1024*100)),
+ MakeTimeAccessor (&HwmpProtocol::m_dot11MeshHWMPperrMinInterval),
+ MakeTimeChecker ()
+ )
+ .AddAttribute ("dot11MeshHWMPactiveRootTimeout",
+ "Lifetime of poractive routing information",
+ TimeValue (MicroSeconds (1024*5000)),
+ MakeTimeAccessor (&HwmpProtocol::m_dot11MeshHWMPactiveRootTimeout),
+ MakeTimeChecker ()
+ )
+ .AddAttribute ("dot11MeshHWMPactivePathTimeout",
+ "Lifetime of reactive routing information",
+ TimeValue (MicroSeconds (1024*5000)),
+ MakeTimeAccessor (&HwmpProtocol::m_dot11MeshHWMPactivePathTimeout),
+ MakeTimeChecker ()
+ )
+ .AddAttribute ("dot11MeshHWMPpathToRootInterval",
+ "Interval between two successive proactive PREQs",
+ TimeValue (MicroSeconds (1024*2000)),
+ MakeTimeAccessor (&HwmpProtocol::m_dot11MeshHWMPpathToRootInterval),
+ MakeTimeChecker ()
+ )
+ .AddAttribute ("dot11MeshHWMPrannInterval",
+ "Lifetime of poractive routing information",
+ TimeValue (MicroSeconds (1024*5000)),
+ MakeTimeAccessor (&HwmpProtocol::m_dot11MeshHWMPrannInterval),
+ MakeTimeChecker ()
+ )
+ .AddAttribute ("maxQueueSize",
+ "Maximum number of packets we can store when resolving route",
+ UintegerValue (255),
+ MakeUintegerAccessor (&HwmpProtocol::m_maxQueueSize),
+ MakeUintegerChecker<uint16_t> (1)
+ )
+ .AddAttribute ("maxTtl",
+ "Initial value of Time To Live field",
+ UintegerValue (32),
+ MakeUintegerAccessor (&HwmpProtocol::m_maxTtl),
+ MakeUintegerChecker<uint8_t> (2)
+ )
+ .AddAttribute ("unicastPerrThreshold",
+ "Maximum number of PERR receivers, when we send a PERR as a chain of unicasts",
+ UintegerValue (32),
+ MakeUintegerAccessor (&HwmpProtocol::m_unicastPerrThreshold),
+ MakeUintegerChecker<uint8_t> (1)
+ )
+ .AddAttribute ("unicastPreqThreshold",
+ "Maximum number of PREQ receivers, when we send a PREQ as a chain of unicasts",
+ UintegerValue (1),
+ MakeUintegerAccessor (&HwmpProtocol::m_unicastPreqThreshold),
+ MakeUintegerChecker<uint8_t> (1)
+ )
+ .AddAttribute ("unicastDataThreshold",
+ "Maximum number ofbroadcast receivers, when we send a broadcast as a chain of unicasts",
+ UintegerValue (1),
+ MakeUintegerAccessor (&HwmpProtocol::m_unicastDataThreshold),
+ MakeUintegerChecker<uint8_t> (1)
+ )
+ .AddAttribute ("doFlag",
+ "Destination only HWMP flag",
+ BooleanValue (true),
+ MakeUintegerAccessor (&HwmpProtocol::m_doFlag),
+ MakeUintegerChecker<bool> ()
+ )
+ .AddAttribute ("rfFlag",
+ "Reply and forward flag",
+ BooleanValue (false),
+ MakeUintegerAccessor (&HwmpProtocol::m_rfFlag),
+ MakeUintegerChecker<bool> ()
+ )
+ .AddAttribute ("RandomStart", "Random delay at first proactive PREQ",
+ TimeValue (Seconds (0.1)),
+ MakeTimeAccessor (&HwmpProtocol::m_randomStart),
+ MakeTimeChecker ()
+ );
+ return tid;
+}
+HwmpProtocol::HwmpProtocol ():
+ m_dataSeqno (1),
+ m_hwmpSeqno (1),
+ m_preqId (0),
+ m_rtable (CreateObject<HwmpRtable> ()),
+ m_isRoot(false)
+{
+}
+
+HwmpProtocol::~HwmpProtocol ()
+{
+}
+
+void
+HwmpProtocol::DoDispose ()
+{
+ for (std::map<Mac48Address, EventId>::iterator i = m_preqTimeouts.begin (); i != m_preqTimeouts.end(); i ++)
+ i->second.Cancel ();
+ m_preqTimeouts.clear ();
+ m_lastDataSeqno.clear ();
+ m_lastHwmpSeqno.clear ();
+ m_rqueue.clear ();
+ m_rtable = 0;
+
+ //TODO: clear plugins
+}
+
+bool
+HwmpProtocol::RequestRoute (
+ uint32_t sourceIface,
+ const Mac48Address source,
+ const Mac48Address destination,
+ Ptr<Packet> packet,
+ uint16_t protocolType, //ethrnet 'Protocol' field
+ MeshL2RoutingProtocol::RouteReplyCallback routeReply
+)
+{
+ HwmpTag tag;
+ if (sourceIface == GetMeshPoint ()->GetIfIndex())
+ // packet from level 3
+ {
+ if(packet->PeekPacketTag(tag))
+ {
+ NS_ASSERT (false);
+ }
+ //Filling TAG:
+ if(destination == Mac48Address::GetBroadcast ())
+ {
+ tag.SetSeqno (m_dataSeqno++);
+ if (m_dataSeqno == 0xffffffff)
+ m_dataSeqno = 0;
+ }
+ tag.SetTtl (m_maxTtl+1);
+ }
+ else
+ {
+ if(!packet->RemovePacketTag(tag))
+ {
+ NS_ASSERT(false);
+ return false;
+ }
+ if (tag.GetTtl () == 0)
+ return false;
+ tag.DecrementTtl ();
+ }
+ if (destination == Mac48Address::GetBroadcast ())
+ {
+ //channel IDs where we have already sent broadcast:
+ std::vector<uint16_t> channels;
+ for(HwmpPluginMap::const_iterator plugin = m_interfaces.begin (); plugin != m_interfaces.end (); plugin ++)
+ {
+ bool should_send = true;
+ for(std::vector<uint16_t>::const_iterator chan = channels.begin(); chan != channels.end(); chan ++)
+ if(*chan == plugin->second->GetChannelId ())
+ should_send = false;
+ if(!should_send)
+ continue;
+ channels.push_back(plugin->second->GetChannelId ());
+ std::vector<Mac48Address> receivers = GetBroadcastReceivers (plugin->first);
+ for (std::vector<Mac48Address>::const_iterator i = receivers.begin (); i != receivers.end(); i ++)
+ {
+ Ptr<Packet> packet_copy = packet->Copy();
+ tag.SetAddress (*i);
+ packet_copy->AddPacketTag (tag);
+ routeReply (true, packet_copy, source, destination, protocolType, plugin->first);
+ }
+ }
+ }
+ else
+ return ForwardUnicast(sourceIface, source, destination, packet, protocolType, routeReply, tag.GetTtl ());
+ return true;
+}
+bool
+HwmpProtocol::ForwardUnicast(uint32_t sourceIface, const Mac48Address source, const Mac48Address destination,
+ Ptr<Packet> packet, uint16_t protocolType, RouteReplyCallback routeReply, uint32_t ttl)
+{
+ NS_ASSERT(destination != Mac48Address::GetBroadcast ());
+ NS_LOG_DEBUG("Requested src = "<<source<<", dst = "<<destination<<", I am "<<GetAddress ());
+ HwmpRtable::LookupResult result = m_rtable->LookupReactive(destination);
+ if(result.retransmitter == Mac48Address::GetBroadcast ())
+ result = m_rtable->LookupProactive ();
+ HwmpTag tag;
+ tag.SetAddress (result.retransmitter);
+ tag.SetTtl (ttl);
+ //seqno and metric is not used;
+ packet->AddPacketTag(tag);
+ if(result.retransmitter != Mac48Address::GetBroadcast ())
+ {
+ //reply immediately:
+ routeReply (true, packet, source, destination, protocolType, result.ifIndex);
+ return true;
+ }
+ if (sourceIface != GetMeshPoint ()->GetIfIndex())
+ {
+ //Start path error procedure:
+ NS_LOG_DEBUG ("Must Send PERR");
+ result = m_rtable->LookupReactiveExpired (destination);
+ //1. Lookup expired reactive path. If exists - start path error
+ // procedure towards a next hop of this path
+ //2. If there was no reactive path, we lookup expired proactive
+ // path. If exist - start path error procedure towards path to
+ // root
+ if(result.retransmitter == Mac48Address::GetBroadcast ())
+ result = m_rtable->LookupProactiveExpired ();
+ if(result.retransmitter == Mac48Address::GetBroadcast ())
+ return false;
+ std::vector<IePerr::FailedDestination> destinations = m_rtable->GetUnreachableDestinations (result.retransmitter);
+ MakePathError (destinations);
+ }
+ //Request a destination:
+ result = m_rtable->LookupReactiveExpired (destination);
+ if(ShouldSendPreq(destination))
+ {
+ uint32_t originator_seqno = GetNextHwmpSeqno ();
+ uint32_t dst_seqno = 0;
+ if(result.retransmitter != Mac48Address::GetBroadcast ())
+ dst_seqno = result.seqnum;
+ for(HwmpPluginMap::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i ++)
+ i->second->RequestDestination(destination, originator_seqno, dst_seqno);
+ }
+ QueuedPacket pkt;
+ pkt.pkt = packet;
+ pkt.dst = destination;
+ pkt.src = source;
+ pkt.protocol = protocolType;
+ pkt.reply = routeReply;
+ pkt.inInterface = sourceIface;
+ return QueuePacket (pkt);
+}
+void
+HwmpProtocol::ReceivePreq (IePreq preq, Mac48Address from, uint32_t interface, uint32_t metric)
+{
+ preq.IncrementMetric (metric);
+ //acceptance cretirea:
+ std::map<Mac48Address, uint32_t>::const_iterator i = m_lastHwmpSeqno.find (preq.GetOriginatorAddress());
+ if (i == m_lastHwmpSeqno.end ())
+ {
+ m_lastHwmpSeqno[preq.GetOriginatorAddress ()] = preq.GetOriginatorSeqNumber();
+ m_lastHwmpMetric[preq.GetOriginatorAddress ()] = preq.GetMetric();
+ }
+ else
+ {
+ if (i->second > preq.GetOriginatorSeqNumber ())
+ return;
+ if (i->second == preq.GetOriginatorSeqNumber ())
+ {
+ //find metric
+ std::map<Mac48Address, uint32_t>::const_iterator j = m_lastHwmpMetric.find (preq.GetOriginatorAddress());
+ NS_ASSERT (j != m_lastHwmpSeqno.end());
+ if (j->second <= preq.GetMetric ())
+ return;
+ }
+ m_lastHwmpSeqno[preq.GetOriginatorAddress ()] = preq.GetOriginatorSeqNumber();
+ m_lastHwmpMetric[preq.GetOriginatorAddress ()] = preq.GetMetric();
+ }
+ NS_LOG_DEBUG("I am "<<GetAddress ()<<"Accepted preq from address"<<from<<", preq:"<<preq);
+ std::vector<Ptr<DestinationAddressUnit> > destinations = preq.GetDestinationList ();
+ for (std::vector<Ptr<DestinationAddressUnit> >::const_iterator i = destinations.begin (); i != destinations.end(); i++)
+ {
+ if ((*i)->GetDestinationAddress () == Mac48Address::GetBroadcast())
+ {
+ //only proactive PREQ contains destination
+ //address as broadcast! Proactive preq MUST
+ //have destination count equal to 1 and
+ //per destination flags DO and RF
+ NS_ASSERT (preq.GetDestCount() == 1);
+ NS_ASSERT (((*i)->IsDo()) && ((*i)->IsRf()));
+ //Add proactive path only if it is the better then existed
+ //before
+ if(
+ ((m_rtable->LookupProactive ()).retransmitter == Mac48Address::GetBroadcast ()) ||
+ ((m_rtable->LookupProactive ()).metric > preq.GetMetric ())
+ )
+ m_rtable->AddProactivePath (
+ preq.GetMetric (),
+ preq.GetOriginatorAddress (),
+ from,
+ interface,
+ MicroSeconds (preq.GetLifetime () * 1024),
+ preq.GetOriginatorSeqNumber ()
+ );
+ ProactivePathResolved ();
+ if (!preq.IsNeedNotPrep ())
+ SendPrep (
+ GetAddress (),
+ preq.GetOriginatorAddress (),
+ from,
+ preq.GetMetric (),
+ preq.GetOriginatorSeqNumber (),
+ GetNextHwmpSeqno (),
+ preq.GetLifetime (),
+ interface
+ );
+ break;
+ }
+ if ((*i)->GetDestinationAddress () == GetAddress ())
+ {
+ preq.DelDestinationAddressElement ((*i)->GetDestinationAddress());
+ SendPrep (
+ GetAddress (),
+ preq.GetOriginatorAddress (),
+ from,
+ (uint32_t)0,
+ preq.GetOriginatorSeqNumber (),
+ GetNextHwmpSeqno (),
+ preq.GetLifetime (),
+ interface
+ );
+ continue;
+ }
+ //check if can answer:
+ HwmpRtable::LookupResult result = m_rtable->LookupReactive ((*i)->GetDestinationAddress());
+ if ((! ((*i)->IsDo())) && (result.retransmitter != Mac48Address::GetBroadcast()))
+ {
+ //have a valid information and acn answer
+ if ((*i)->IsRf ())
+ (*i)->SetFlags (true, false, (*i)->IsUsn ()); //DO = 1, RF = 0 (as it was)
+ else
+ {
+ //send a PREP and delete destination
+ preq.DelDestinationAddressElement ((*i)->GetDestinationAddress());
+ SendPrep (
+ (*i)->GetDestinationAddress (),
+ preq.GetOriginatorAddress (),
+ from,
+ result.metric,
+ preq.GetOriginatorSeqNumber (),
+ result.seqnum +1,
+ preq.GetLifetime (),
+ interface
+ );
+ continue;
+ }
+ }
+ }
+ if (
+ ((m_rtable->LookupReactive(preq.GetOriginatorAddress ())).retransmitter == Mac48Address::GetBroadcast ()) ||
+ ((m_rtable->LookupReactive(preq.GetOriginatorAddress ())).metric > preq.GetMetric ())
+ )
+ m_rtable->AddReactivePath (
+ preq.GetOriginatorAddress (),
+ from,
+ interface,
+ preq.GetMetric (),
+ MicroSeconds (preq.GetLifetime () *1024),
+ preq.GetOriginatorSeqNumber ()
+ );
+ ReactivePathResolved (preq.GetOriginatorAddress ());
+ //chack if must retransmit:
+ if (preq.GetDestCount () == 0)
+ return;
+ //Forward PREQ to all interfaces:
+ NS_LOG_DEBUG("I am "<<GetAddress ()<<"retransmitting PREQ:"<<preq);
+ for(HwmpPluginMap::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i ++)
+ i->second->SendPreq (preq);
+}
+void
+HwmpProtocol::ReceivePrep (IePrep prep, Mac48Address from, uint32_t interface, uint32_t metric)
+{
+ prep.IncrementMetric (metric);
+ //acceptance cretirea:
+ std::map<Mac48Address, uint32_t>::const_iterator i = m_lastHwmpSeqno.find (prep.GetOriginatorAddress());
+ if (i == m_lastHwmpSeqno.end ())
+ {
+ m_lastHwmpSeqno[prep.GetOriginatorAddress ()] = prep.GetOriginatorSeqNumber();
+ }
+ else
+ {
+ if (i->second >= prep.GetOriginatorSeqNumber ())
+ return;
+ else
+ m_lastHwmpSeqno[prep.GetOriginatorAddress ()] = prep.GetOriginatorSeqNumber();
+ }
+ //update routing info
+ //Now add a path to destination and add precursor to source
+ NS_LOG_DEBUG("I am "<<GetAddress ()<<", received prep from "<<prep.GetOriginatorAddress ()<<", receiver was:"<<from);
+ HwmpRtable::LookupResult result = m_rtable->LookupReactive(prep.GetDestinationAddress());
+ //Add a reactive path only if it is better than existing:
+ m_rtable->AddPrecursor (prep.GetDestinationAddress (), interface, from);
+ if (
+ ((m_rtable->LookupReactive(prep.GetOriginatorAddress ())).retransmitter == Mac48Address::GetBroadcast ()) ||
+ ((m_rtable->LookupReactive(prep.GetOriginatorAddress ())).metric > prep.GetMetric ())
+ )
+ {
+ m_rtable->AddReactivePath (
+ prep.GetOriginatorAddress (),
+ from,
+ interface,
+ prep.GetMetric (),
+ MicroSeconds(prep.GetLifetime () * 1024),
+ prep.GetOriginatorSeqNumber ());
+ if(result.retransmitter != Mac48Address::GetBroadcast ())
+ m_rtable->AddPrecursor (prep.GetOriginatorAddress (), interface, result.retransmitter);
+ ReactivePathResolved (prep.GetOriginatorAddress ());
+ }
+ if(prep.GetDestinationAddress () == GetAddress ())
+ {
+ NS_LOG_DEBUG("I am "<<GetAddress ()<<", resolved "<<prep.GetOriginatorAddress ());
+ return;
+ }
+ if (result.retransmitter == Mac48Address::GetBroadcast ())
+ //try to look for default route
+ result = m_rtable->LookupProactive ();
+ if (result.retransmitter == Mac48Address::GetBroadcast ())
+ return;
+ //Forward PREP
+ HwmpPluginMap::const_iterator prep_sender = m_interfaces.find (result.ifIndex);
+ NS_ASSERT(prep_sender != m_interfaces.end ());
+ prep_sender->second->SendPrep(prep, result.retransmitter);
+}
+void
+HwmpProtocol::ReceivePerr (IePerr perr, Mac48Address from, uint32_t interface)
+{
+ //Acceptance cretirea:
+ NS_LOG_DEBUG("I am "<<GetAddress ()<<", received PERR from "<<from);
+ std::vector<IePerr::FailedDestination> destinations = perr.GetAddressUnitVector ();
+ HwmpRtable::LookupResult result;
+ for(unsigned int i = 0; i < destinations.size (); i ++)
+ {
+ result = m_rtable->LookupReactive (destinations[i].destination);
+ NS_LOG_DEBUG("Destination = "<<destinations[i].destination<<", RA = "<<result.retransmitter);
+ if (
+ (result.retransmitter != from) ||
+ (result.ifIndex != interface) ||
+ (result.seqnum > destinations[i].seqnum)
+ )
+ {
+ perr.DeleteAddressUnit(destinations[i].destination);
+ continue;
+ }
+ m_rtable->DeleteReactivePath(destinations[i].destination);
+ }
+ if(perr.GetNumOfDest () == 0)
+ return;
+ MakePathError (destinations);
+}
+void
+HwmpProtocol::SendPrep (
+ Mac48Address src,
+ Mac48Address dst,
+ Mac48Address retransmitter,
+ uint32_t initMetric,
+ uint32_t originatorDsn,
+ uint32_t destinationSN,
+ uint32_t lifetime,
+ uint32_t interface)
+{
+ IePrep prep;
+ prep.SetHopcount (0);
+ prep.SetTtl (m_maxTtl);
+ prep.SetDestinationAddress (dst);
+ prep.SetDestinationSeqNumber (destinationSN);
+ prep.SetLifetime (lifetime);
+ prep.SetMetric (0);
+ prep.SetOriginatorAddress (src);
+ prep.SetOriginatorSeqNumber (originatorDsn);
+ HwmpPluginMap::const_iterator prep_sender = m_interfaces.find (interface);
+ NS_ASSERT(prep_sender != m_interfaces.end ());
+ prep_sender->second->SendPrep(prep, retransmitter);
+ //m_prepCallback (prep, retransmitter);
+
+}
+bool
+HwmpProtocol::Install (Ptr<MeshPointDevice> mp)
+{
+ m_mp = mp;
+ std::vector<Ptr<NetDevice> > interfaces = mp->GetInterfaces ();
+ for (std::vector<Ptr<NetDevice> >::const_iterator i = interfaces.begin (); i != interfaces.end(); i++)
+ {
+ // Checking for compatible net device
+ const WifiNetDevice * wifiNetDev = dynamic_cast<const WifiNetDevice *> (PeekPointer (*i));
+ if (wifiNetDev == NULL)
+ return false;
+ MeshWifiInterfaceMac * mac = dynamic_cast<MeshWifiInterfaceMac *> (PeekPointer (wifiNetDev->GetMac ()));
+ if (mac == NULL)
+ return false;
+ // Installing plugins:
+ Ptr<HwmpMacPlugin> hwmpMac = Create<HwmpMacPlugin> (wifiNetDev->GetIfIndex (), this);
+ m_interfaces[wifiNetDev->GetIfIndex ()] = hwmpMac;
+ mac->InstallPlugin (hwmpMac);
+ }
+ mp->SetRoutingProtocol (this);
+ // Mesh point aggregates all installed protocols
+ mp->AggregateObject (this);
+ m_address = Mac48Address::ConvertFrom (mp->GetAddress ());//* address;
+ return true;
+}
+void
+HwmpProtocol::PeerLinkStatus(Mac48Address meshPointAddress, Mac48Address peerAddress, uint32_t interface, bool status)
+{
+ if(status)
+ {
+ HwmpRtable::LookupResult result = m_rtable->LookupReactive(meshPointAddress);
+ HwmpPluginMap::const_iterator i = m_interfaces.find(interface);
+ NS_ASSERT(i != m_interfaces.end ());
+ if(result.metric < i->second->GetLinkMetric(peerAddress))
+ {
+ m_rtable->AddReactivePath(meshPointAddress, peerAddress, interface, 1, Seconds (0), i->second->GetLinkMetric(peerAddress));
+ ReactivePathResolved (meshPointAddress);
+ }
+ }
+ else
+ {
+ std::vector<IePerr::FailedDestination> destinations = m_rtable->GetUnreachableDestinations (peerAddress);
+ MakePathError (destinations);
+ }
+}
+void
+HwmpProtocol::SetNeighboursCallback(Callback<std::vector<Mac48Address>, uint32_t> cb)
+{
+ m_neighboursCallback = cb;
+}
+bool
+HwmpProtocol::DropDataFrame(uint32_t seqno, Mac48Address source)
+{
+ std::map<Mac48Address, uint32_t,std::less<Mac48Address> >::const_iterator i = m_lastDataSeqno.find (source);
+ if (i == m_lastDataSeqno.end ())
+ m_lastDataSeqno[source] = seqno;
+ else
+ {
+ if (i->second >= seqno)
+ return true;
+ m_lastDataSeqno[source] = seqno;
+ }
+ return false;
+}
+void
+HwmpProtocol::MakePathError (std::vector<IePerr::FailedDestination> destinations)
+{
+ //HwmpRtable increments a sequence number as written in 11B.9.7.2
+ std::vector<std::pair<uint32_t, Mac48Address> > receivers = GetPerrReceivers (destinations);
+ if(receivers.size () == 0)
+ return;
+ IePerr perr;
+ for(unsigned int i = 0; i < destinations.size (); i ++)
+ {
+ perr.AddAddressUnit(destinations[i]);
+ m_rtable->DeleteReactivePath(destinations[i].destination);
+ }
+ for(HwmpPluginMap::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i ++)
+ {
+ std::vector<Mac48Address> receivers_for_interface;
+ for(unsigned int j = 0; j < receivers.size(); j ++)
+ if(i->first == receivers[j].first)
+ receivers_for_interface.push_back(receivers[j].second);
+ i->second->SendPerr (perr, receivers_for_interface);
+ }
+}
+std::vector<std::pair<uint32_t, Mac48Address> >
+HwmpProtocol::GetPerrReceivers (std::vector<IePerr::FailedDestination> failedDest)
+{
+ HwmpRtable::PrecursorList retval;
+ for (unsigned int i = 0; i < failedDest.size (); i ++)
+ {
+ HwmpRtable::PrecursorList precursors = m_rtable->GetPrecursors(failedDest[i].destination);
+ m_rtable->DeleteReactivePath (failedDest[i].destination);
+ m_rtable->DeleteProactivePath(failedDest[i].destination);
+ for (unsigned int j = 0; j < precursors.size (); j ++)
+ retval.push_back(precursors[j]);
+ }
+ //Check if we have dublicates in retval and precursors:
+ for (unsigned int i = 0; i < retval.size(); i ++)
+ for (unsigned int j = i; j < retval.size(); j ++)
+ if(retval[i].second == retval[j].second)
+ retval.erase(retval.begin() + j);
+ return retval;
+}
+std::vector<Mac48Address>
+HwmpProtocol::GetPreqReceivers (uint32_t interface)
+{
+ std::vector<Mac48Address> retval;
+ if(!m_neighboursCallback.IsNull ())
+ retval = m_neighboursCallback (interface);
+ if ((retval.size() >= m_unicastPreqThreshold) || (retval.size () == 0))
+ {
+ retval.clear ();
+ retval.push_back (Mac48Address::GetBroadcast ());
+ }
+ return retval;
+}
+std::vector<Mac48Address>
+HwmpProtocol::GetBroadcastReceivers (uint32_t interface)
+{
+ std::vector<Mac48Address> retval;
+ if(!m_neighboursCallback.IsNull ())
+ retval = m_neighboursCallback (interface);
+ if ((retval.size() >= m_unicastDataThreshold) || (retval.size () == 0))
+ {
+ retval.clear ();
+ retval.push_back (Mac48Address::GetBroadcast ());
+ }
+ return retval;
+}
+
+bool
+HwmpProtocol::QueuePacket (QueuedPacket packet)
+{
+ if (m_rqueue.size () > m_maxQueueSize)
+ return false;
+ m_rqueue.push_back (packet);
+ return true;
+}
+
+MeshL2RoutingProtocol::QueuedPacket
+HwmpProtocol::DequeueFirstPacketByDst (Mac48Address dst)
+{
+ QueuedPacket retval;
+ retval.pkt = NULL;
+ for(std::vector<QueuedPacket>::iterator i = m_rqueue.begin (); i != m_rqueue.end (); i++)
+ if((*i).dst == dst)
+ {
+ retval = (*i);
+ m_rqueue.erase (i);
+ break;
+ }
+ return retval;
+}
+MeshL2RoutingProtocol::QueuedPacket
+HwmpProtocol::DequeueFirstPacket ()
+{
+ QueuedPacket retval;
+ retval.pkt = NULL;
+ if(m_rqueue.size () != 0)
+ {
+ retval = m_rqueue[0];
+ m_rqueue.erase (m_rqueue.begin ());
+ }
+ return retval;
+}
+void
+HwmpProtocol::ReactivePathResolved (Mac48Address dst)
+{
+ HwmpRtable::LookupResult result = m_rtable->LookupReactive (dst);
+ NS_ASSERT(result.retransmitter != Mac48Address::GetBroadcast ());
+ //Send all packets stored for this destination
+ QueuedPacket packet;
+ while (1)
+ {
+ packet = DequeueFirstPacketByDst (dst);
+ if (packet.pkt == NULL)
+ return;
+ //set RA tag for retransmitter:
+ HwmpTag tag;
+ packet.pkt->RemovePacketTag(tag);
+ tag.SetAddress (result.retransmitter);
+ packet.pkt->AddPacketTag (tag);
+ packet.reply (true, packet.pkt, packet.src, packet.dst, packet.protocol, result.ifIndex);
+ }
+}
+void
+HwmpProtocol::ProactivePathResolved ()
+{
+ //send all packets to root
+ HwmpRtable::LookupResult result = m_rtable->LookupProactive ();
+ NS_ASSERT(result.retransmitter != Mac48Address::GetBroadcast ());
+ QueuedPacket packet;
+ while (1)
+ {
+ packet = DequeueFirstPacket ();
+ if (packet.pkt == NULL)
+ return;
+ //set RA tag for retransmitter:
+ HwmpTag tag;
+ NS_ASSERT (packet.pkt->PeekPacketTag(tag));
+ tag.SetAddress (result.retransmitter);
+ packet.pkt->AddPacketTag (tag);
+ packet.reply (true, packet.pkt, packet.src, packet.dst, packet.protocol, result.ifIndex);
+ }
+
+}
+
+bool
+HwmpProtocol::ShouldSendPreq (Mac48Address dst)
+{
+ std::map<Mac48Address, EventId>::const_iterator i = m_preqTimeouts.find (dst);
+ if (i == m_preqTimeouts.end ())
+ {
+ m_preqTimeouts[dst] = Simulator::Schedule (
+ MilliSeconds (2*(m_dot11MeshHWMPnetDiameterTraversalTime.GetMilliSeconds())),
+ &HwmpProtocol::RetryPathDiscovery, this, dst, 0);
+ return true;
+ }
+ return false;
+}
+void
+HwmpProtocol::RetryPathDiscovery (Mac48Address dst, uint8_t numOfRetry)
+{
+ HwmpRtable::LookupResult result = m_rtable->LookupReactive (dst);
+ if(result.retransmitter == Mac48Address::GetBroadcast ())
+ result = m_rtable->LookupProactive ();
+ if (result.retransmitter != Mac48Address::GetBroadcast ())
+ {
+ std::map<Mac48Address, EventId>::iterator i = m_preqTimeouts.find (dst);
+ NS_ASSERT (i != m_preqTimeouts.end());
+ m_preqTimeouts.erase (i);
+ return;
+ }
+ numOfRetry++;
+ if (numOfRetry > m_dot11MeshHWMPmaxPREQretries)
+ {
+ QueuedPacket packet;
+ //purge queue and delete entry from retryDatabase
+ while (1)
+ {
+ packet = DequeueFirstPacketByDst (dst);
+ if (packet.pkt == NULL)
+ break;
+ packet.reply (false, packet.pkt, packet.src, packet.dst, packet.protocol, HwmpRtable::MAX_METRIC);
+ }
+ std::map<Mac48Address, EventId>::iterator i = m_preqTimeouts.find (dst);
+ NS_ASSERT (i != m_preqTimeouts.end());
+ m_preqTimeouts.erase (i);
+ return;
+ }
+ uint32_t originator_seqno = GetNextHwmpSeqno ();
+ uint32_t dst_seqno = 0;
+ if(result.retransmitter != Mac48Address::GetBroadcast ())
+ dst_seqno = result.seqnum;
+ for(HwmpPluginMap::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i ++)
+ i->second->RequestDestination(dst, originator_seqno, dst_seqno);
+ m_preqTimeouts[dst] = Simulator::Schedule (
+ MilliSeconds (2*(m_dot11MeshHWMPnetDiameterTraversalTime.GetMilliSeconds())),
+ &HwmpProtocol::RetryPathDiscovery, this, dst, numOfRetry);
+}
+//Proactive PREQ routines:
+void
+HwmpProtocol::SetRoot ()
+{
+ UniformVariable coefficient (0.0, m_randomStart.GetSeconds());
+ Time randomStart = Seconds (coefficient.GetValue());
+ m_proactivePreqTimer = Simulator::Schedule (randomStart, &HwmpProtocol::SendProactivePreq, this);
+ NS_LOG_UNCOND("ROOT IS: "<<m_address);
+ SendProactivePreq ();
+ m_isRoot = true;
+}
+void
+HwmpProtocol::UnsetRoot ()
+{
+ m_proactivePreqTimer.Cancel ();
+}
+void
+HwmpProtocol::SendProactivePreq ()
+{
+ IePreq preq;
+ //By default: must answer
+ preq.SetHopcount (0);
+ preq.SetTTL (m_maxTtl);
+ if (m_preqId == 0xffffffff)
+ m_preqId = 0;
+ preq.SetLifetime (m_dot11MeshHWMPactiveRootTimeout.GetMicroSeconds () /1024);
+ //\attention: do not forget to set originator address, sequence
+ //number and preq ID in HWMP-MAC plugin
+ preq.AddDestinationAddressElement (true, true, Mac48Address::GetBroadcast (), 0);
+ preq.SetOriginatorAddress(GetAddress ());
+ preq.SetPreqID (GetNextPreqId ());
+ preq.SetOriginatorSeqNumber (GetNextHwmpSeqno ());
+ for(HwmpPluginMap::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i ++)
+ i->second->SendPreq(preq);
+ m_proactivePreqTimer = Simulator::Schedule (m_dot11MeshHWMPpathToRootInterval, &HwmpProtocol::SendProactivePreq, this);
+}
+bool
+HwmpProtocol::GetDoFlag ()
+{
+ return m_doFlag;
+}
+bool
+HwmpProtocol::GetRfFlag ()
+{
+ return m_rfFlag;
+}
+Time
+HwmpProtocol::GetPreqMinInterval ()
+{
+ return m_dot11MeshHWMPpreqMinInterval;
+}
+Time
+HwmpProtocol::GetPerrMinInterval ()
+{
+ return m_dot11MeshHWMPperrMinInterval;
+}
+uint8_t
+HwmpProtocol::GetMaxTtl ()
+{
+ return m_maxTtl;
+}
+uint32_t
+HwmpProtocol::GetNextPreqId ()
+{
+ m_preqId ++;
+ if(m_preqId == 0xffffffff)
+ m_preqId = 0;
+ return m_preqId;
+}
+uint32_t
+HwmpProtocol::GetNextHwmpSeqno ()
+{
+ m_hwmpSeqno ++;
+ if(m_hwmpSeqno == 0xffffffff)
+ m_hwmpSeqno = 1;
+ return m_hwmpSeqno;
+}
+uint32_t
+HwmpProtocol::GetActivePathLifetime ()
+{
+ return m_dot11MeshHWMPactivePathTimeout.GetMicroSeconds () / 1024;
+}
+uint8_t
+HwmpProtocol::GetUnicastPerrThreshold()
+{
+ return m_unicastPerrThreshold;
+}
+Mac48Address
+HwmpProtocol::GetAddress ()
+{
+ return m_address;
+}
+} //namespace dot11s
+} //namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/hwmp-protocol.h Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,218 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#ifndef HWMP_PROTOCOL_H
+#define HWMP_PROTOCOL_H
+
+#include "ns3/mesh-l2-routing-protocol.h"
+#include "ns3/nstime.h"
+#include "ns3/ie-dot11s-perr.h"
+#include "ns3/event-id.h"
+#include <vector>
+#include <map>
+
+namespace ns3 {
+class MeshPointDevice;
+class Packet;
+class Mac48Address;
+namespace dot11s {
+class HwmpMacPlugin;
+class HwmpRtable;
+class IePreq;
+class IePrep;
+/**
+ * \ingroup dot11s
+ *
+ * \brief Hybrid wireless mesh protocol -- a routing protocol of IEEE 802.11s draft.
+ */
+class HwmpProtocol : public MeshL2RoutingProtocol
+{
+public:
+ static TypeId GetTypeId ();
+ HwmpProtocol ();
+ ~HwmpProtocol ();
+ void DoDispose ();
+
+ /// Route request, inherited from MeshL2RoutingProtocol
+ bool RequestRoute (uint32_t sourceIface, const Mac48Address source, const Mac48Address destination,
+ Ptr<Packet> packet, uint16_t protocolType, RouteReplyCallback routeReply);
+ /**
+ * \brief Install HWMP on given mesh point.
+ *
+ * Installing protocol cause installing its interface MAC plugins.
+ *
+ * Also MP aggregates all installed protocols, HWMP protocol can be accessed
+ * via MeshPointDevice::GetObject<dot11s::HwmpProtocol>();
+ */
+ bool Install (Ptr<MeshPointDevice>);
+ void PeerLinkStatus(Mac48Address meshPontAddress, Mac48Address peerAddress, uint32_t interface,bool status);
+ ///\brief This callback is used to obtain active neighbours on a
+ //given interface
+ ///\param interface is the interface ID
+ void SetNeighboursCallback(Callback<std::vector<Mac48Address>, uint32_t> cb);
+ ///\name Proactive PREQ mechanism:
+ ///\{
+ void SetRoot ();
+ void UnsetRoot ();
+ ///\}
+private:
+ friend class HwmpMacPlugin;
+
+ /// Like RequestRoute, but for unicast packets
+ bool ForwardUnicast (uint32_t sourceIface, const Mac48Address source, const Mac48Address destination,
+ Ptr<Packet> packet, uint16_t protocolType, RouteReplyCallback routeReply, uint32_t ttl);
+
+ ///\name Interaction with HWMP MAC plugin
+ //\{
+ void ReceivePreq(IePreq preq, Mac48Address from, uint32_t interface, uint32_t metric);
+ void ReceivePrep(IePrep prep, Mac48Address from, uint32_t interface, uint32_t metric);
+ void ReceivePerr(IePerr perr, Mac48Address from, uint32_t interface);
+ void SendPrep (
+ Mac48Address src,
+ Mac48Address dst,
+ Mac48Address retransmitter,
+ uint32_t initMetric,
+ uint32_t originatorDsn,
+ uint32_t destinationSN,
+ uint32_t lifetime,
+ uint32_t interface);
+
+ ///\brief forms a path error information element when list of destination fails on a given interface
+ void MakePathError (std::vector<IePerr::FailedDestination> destinations);
+ /// \return list of addresses where a PERR should be sent to
+ std::vector<std::pair<uint32_t, Mac48Address> > GetPerrReceivers (std::vector<IePerr::FailedDestination> failedDest);
+
+ /// \return list of addresses where a PERR should be sent to
+ std::vector<Mac48Address> GetPreqReceivers (uint32_t interface);
+ /// \return list of addresses where a broadcast should be
+ //retransmitted
+ std::vector<Mac48Address> GetBroadcastReceivers (uint32_t interface);
+ /**
+ * \brief MAC-plugin asks wether the frame can be dropeed. Protocol automatically updates seqno.
+ *
+ * \return true if frame can be dropped
+ * \param uint32_t is the seqno
+ * \param Mac48Address is the mesh source addrress of the frame
+ */
+ bool DropDataFrame(uint32_t, Mac48Address);
+ //\}
+private:
+ ///\name Methods related to Queue/Dequeue procedures
+ //\{
+ bool QueuePacket (MeshL2RoutingProtocol::QueuedPacket packet);
+ QueuedPacket DequeueFirstPacketByDst (Mac48Address dst);
+ QueuedPacket DequeueFirstPacket ();
+ void ReactivePathResolved (Mac48Address dst);
+ void ProactivePathResolved ();
+ //\}
+
+ ///\name Methods responsible for path discovery retry procedure:
+ //\{
+
+ /**
+ * \brief checks when the last path discovery procedure was started for a given destination.
+ *
+ * If the retry counter has not achieved the maximum level - preq should not be sent
+ */
+ bool ShouldSendPreq (Mac48Address dst);
+
+ /**
+ * \brief Generates PREQ retry when retry timeout has expired and route is still unresolved.
+ *
+ * When PREQ retry has achieved the maximum level - retry mechanish should be cancelled
+ */
+ void RetryPathDiscovery (Mac48Address dst, uint8_t numOfRetry);
+ //\}
+
+ ///\name Proactive Preq routines:
+ //\{
+ void SendProactivePreq ();
+ //\}
+ ///\return address of MeshPointDevice
+ Mac48Address GetAddress ();
+private:
+ typedef std::map<uint32_t, Ptr<HwmpMacPlugin> > HwmpPluginMap;
+ HwmpPluginMap m_interfaces;
+ Mac48Address m_address;
+ uint32_t m_dataSeqno;
+ uint32_t m_hwmpSeqno;
+ uint32_t m_preqId;
+ ///\name Sequence number filters
+ //\{
+ /// Data sequence number database
+ std::map<Mac48Address, uint32_t> m_lastDataSeqno;
+ /// DSN databse
+ std::map<Mac48Address, uint32_t> m_lastHwmpSeqno;
+ /// Metric database
+ std::map<Mac48Address, uint32_t> m_lastHwmpMetric;
+ //\}
+
+ /// Routing table
+ Ptr<HwmpRtable> m_rtable;
+
+ ///\name Timers:
+ //\{
+ std::map<Mac48Address, EventId> m_preqTimeouts;
+ EventId m_proactivePreqTimer;
+ //Random start in Proactive PREQ propagation
+ Time m_randomStart;
+ //\}
+
+ /// Packet Queue
+ std::vector<QueuedPacket> m_rqueue;
+private:
+ ///\name HWMP-protocol parameters (attributes of GetTypeId)
+ //\{
+ uint16_t m_maxQueueSize;
+ uint8_t m_dot11MeshHWMPmaxPREQretries;
+ Time m_dot11MeshHWMPnetDiameterTraversalTime;
+ Time m_dot11MeshHWMPpreqMinInterval;
+ Time m_dot11MeshHWMPperrMinInterval;
+ Time m_dot11MeshHWMPactiveRootTimeout;
+ Time m_dot11MeshHWMPactivePathTimeout;
+ Time m_dot11MeshHWMPpathToRootInterval;
+ Time m_dot11MeshHWMPrannInterval;
+ bool m_isRoot;
+ uint8_t m_maxTtl;
+ uint8_t m_unicastPerrThreshold;
+ uint8_t m_unicastPreqThreshold;
+ uint8_t m_unicastDataThreshold;
+ bool m_doFlag;
+ bool m_rfFlag;
+ //\}
+
+ ///\name Methods needed by HwmpMacLugin to access protocol parameters:
+ //\{
+ bool GetDoFlag ();
+ bool GetRfFlag ();
+ Time GetPreqMinInterval ();
+ Time GetPerrMinInterval ();
+ uint8_t GetMaxTtl ();
+ uint32_t GetNextPreqId ();
+ uint32_t GetNextHwmpSeqno ();
+ uint32_t GetActivePathLifetime ();
+ uint8_t GetUnicastPerrThreshold ();
+ //\}
+ Callback <std::vector<Mac48Address>, uint32_t> m_neighboursCallback;
+};
+} //namespace dot11s
+} //namespace ns3
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/hwmp-rtable.cc Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,367 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#include "ns3/object.h"
+#include "ns3/assert.h"
+#include "ns3/simulator.h"
+#include "ns3/test.h"
+#include "ns3/log.h"
+
+#include "hwmp-rtable.h"
+
+namespace ns3 {
+namespace dot11s {
+
+NS_LOG_COMPONENT_DEFINE ("HwmpRtable");
+
+NS_OBJECT_ENSURE_REGISTERED (HwmpRtable);
+
+TypeId
+HwmpRtable::GetTypeId ()
+{
+ static TypeId tid = TypeId ("ns3::dot11s::HwmpRtable")
+ .SetParent<Object> ()
+ .AddConstructor<HwmpRtable> ();
+ return tid;
+}
+
+HwmpRtable::HwmpRtable ()
+{
+ DeleteProactivePath ();
+}
+
+HwmpRtable::~HwmpRtable ()
+{
+ DoDispose ();
+}
+
+void
+HwmpRtable::DoDispose ()
+{
+ m_routes.clear ();
+}
+
+void
+HwmpRtable::AddReactivePath (
+ Mac48Address destination,
+ Mac48Address retransmitter,
+ uint32_t interface,
+ uint32_t metric,
+ Time lifetime,
+ uint32_t seqnum
+)
+{
+ std::map<Mac48Address, ReactiveRoute>::iterator i = m_routes.find (destination);
+ if (i == m_routes.end ())
+ {
+ ReactiveRoute newroute;
+ m_routes[destination] = newroute;
+ }
+ i = m_routes.find (destination);
+ NS_ASSERT (i != m_routes.end());
+ i->second.retransmitter = retransmitter;
+ i->second.interface = interface;
+ i->second.metric = metric;
+ if (lifetime != Seconds (0))
+ i->second.whenExpire = MilliSeconds (Simulator::Now().GetMilliSeconds() + lifetime.GetMilliSeconds());
+ else
+ // Information about peer does not have lifetime
+ i->second.whenExpire = Seconds (0);
+ i->second.seqnum = seqnum;
+}
+
+void
+HwmpRtable::AddProactivePath (
+ uint32_t metric,
+ Mac48Address root,
+ Mac48Address retransmitter,
+ uint32_t interface,
+ Time lifetime,
+ uint32_t seqnum
+)
+{
+ m_root.root = root;
+ m_root.retransmitter = retransmitter;
+ m_root.metric = metric;
+ m_root.whenExpire = MilliSeconds (Simulator::Now().GetMilliSeconds() + lifetime.GetMilliSeconds());
+ m_root.seqnum = seqnum;
+ m_root.interface = interface;
+}
+
+void
+HwmpRtable::AddPrecursor (Mac48Address destination, uint32_t precursorInterface, Mac48Address precursorAddress)
+{
+ std::pair<uint32_t, Mac48Address> precursor;
+ precursor.first = precursorInterface;
+ precursor.second = precursorAddress;
+ std::map<Mac48Address, ReactiveRoute>::iterator i = m_routes.find (destination);
+ if (i != m_routes.end ())
+ {
+ bool should_add = true;
+ for (unsigned int j = 0 ; j < i->second.precursors.size (); j ++)
+ //NB: Only one active route may exist, so do not check
+ //interface ID, just address
+ if (i->second.precursors[j].second == precursorAddress)
+ {
+ should_add = false;
+ break;
+ }
+ if (should_add)
+ i->second.precursors.push_back (precursor);
+ }
+ if(m_root.root == destination)
+ for (unsigned int j = 0 ; j < m_root.precursors.size (); j ++)
+ if (m_root.precursors[j].second == precursorAddress)
+ return;
+ m_root.precursors.push_back(precursor);
+}
+
+void
+HwmpRtable::DeleteProactivePath ()
+{
+ m_root.precursors.clear ();
+ m_root.interface = INTERFACE_ANY;
+ m_root.metric = MAX_METRIC;
+ m_root.retransmitter = Mac48Address::GetBroadcast ();
+ m_root.seqnum = 0;
+ m_root.whenExpire = Simulator::Now ();
+}
+
+void
+HwmpRtable::DeleteProactivePath (Mac48Address root)
+{
+ if(m_root.root == root)
+ DeleteProactivePath ();
+}
+
+void
+HwmpRtable::DeleteReactivePath (Mac48Address destination)
+{
+ std::map<Mac48Address, ReactiveRoute>::iterator i = m_routes.find (destination);
+ if (i != m_routes.end ())
+ m_routes.erase (i);
+}
+
+HwmpRtable::LookupResult
+HwmpRtable::LookupReactive (Mac48Address destination)
+{
+ std::map<Mac48Address, ReactiveRoute>::iterator i = m_routes.find (destination);
+ if (i == m_routes.end ())
+ return LookupResult ();
+ if ((i->second.whenExpire < Simulator::Now ()) && (i->second.whenExpire != Seconds (0)))
+ {
+ NS_LOG_DEBUG ("Reactive route has expired, sorry.");
+ return LookupResult();
+ }
+ return LookupResult (i->second.retransmitter, i->second.interface, i->second.metric, i->second.seqnum);
+}
+
+HwmpRtable::LookupResult
+HwmpRtable::LookupReactiveExpired (Mac48Address destination)
+{
+ std::map<Mac48Address, ReactiveRoute>::iterator i = m_routes.find (destination);
+ if (i == m_routes.end ())
+ return LookupResult ();
+ return LookupResult (i->second.retransmitter, i->second.interface, i->second.metric, i->second.seqnum);
+}
+
+HwmpRtable::LookupResult
+HwmpRtable::LookupProactive ()
+{
+ if (m_root.whenExpire < Simulator::Now ())
+ {
+ NS_LOG_DEBUG ("Proactive route has expired and will be deleted, sorry.");
+ DeleteProactivePath ();
+ }
+ return LookupProactiveExpired ();
+}
+
+HwmpRtable::LookupResult
+HwmpRtable::LookupProactiveExpired ()
+{
+ return LookupResult(m_root.retransmitter, m_root.interface, m_root.metric, m_root.seqnum);
+}
+
+std::vector<IePerr::FailedDestination>
+HwmpRtable::GetUnreachableDestinations (Mac48Address peerAddress)
+{
+ IePerr::FailedDestination dst;
+ std::vector<IePerr::FailedDestination> retval;
+ for (std::map<Mac48Address, ReactiveRoute>::iterator i = m_routes.begin (); i != m_routes.end(); i++)
+ if (i->second.retransmitter == peerAddress)
+ {
+ dst.destination = i->first;
+ i->second.seqnum ++;
+ dst.seqnum = i->second.seqnum;
+ retval.push_back (dst);
+ }
+ //Lookup a path to root
+ if (m_root.retransmitter == peerAddress)
+ {
+ dst.destination = m_root.root;
+ dst.seqnum = m_root.seqnum;
+ retval.push_back (dst);
+ }
+ return retval;
+}
+
+HwmpRtable::PrecursorList
+HwmpRtable::GetPrecursors (Mac48Address destination)
+{
+ //We suppose that no dublicates here can be
+ PrecursorList retval;
+ std::map<Mac48Address, ReactiveRoute>::iterator route = m_routes.find (destination);
+ if (route != m_routes.end ())
+ for (unsigned int i = 0; i < route->second.precursors.size (); i ++)
+ retval.push_back(route->second.precursors[i]);
+ if (m_root.root == destination)
+ for (unsigned int i = 0; i < m_root.precursors.size (); i ++)
+ {
+ bool should_add = true;
+ for(unsigned int j = 0; j < retval.size(); j ++)
+ if(retval[j].second == m_root.precursors[i].second)
+ {
+ should_add = false;
+ break;
+ }
+ if(should_add)
+ retval.push_back(m_root.precursors[i]);
+ }
+ return retval;
+}
+
+bool HwmpRtable::LookupResult::operator==(const HwmpRtable::LookupResult & o) const
+{
+ return (retransmitter == o.retransmitter
+ && ifIndex == o.ifIndex
+ && metric == o.metric
+ && seqnum == o.seqnum
+ );
+}
+
+bool HwmpRtable::LookupResult::IsValid() const
+{
+ return !( retransmitter == Mac48Address::GetBroadcast ()
+ && ifIndex == INTERFACE_ANY
+ && metric == MAX_METRIC
+ && seqnum == 0
+ );
+}
+
+#ifdef RUN_SELF_TESTS
+
+/// Unit test for HwmpRtable
+class HwmpRtableTest : public Test
+{
+public:
+ HwmpRtableTest ();
+ virtual bool RunTests();
+
+private:
+ void Test1 ();
+ void Test2 ();
+ void Test3 ();
+ void Test4 ();
+
+private:
+ bool result;
+
+ Mac48Address dst;
+ Mac48Address hop;
+ uint32_t iface;
+ uint32_t metric;
+ uint32_t seqnum;
+ Time expire;
+ Ptr<HwmpRtable> table;
+};
+
+/// Test instance
+static HwmpRtableTest g_HwmpRtableTest;
+
+HwmpRtableTest::HwmpRtableTest () : Test ("Mesh/802.11s/HwmpRtable"),
+ result(true),
+ dst ("01:00:00:01:00:01"),
+ hop ("01:00:00:01:00:03"),
+ iface (8010),
+ metric (10),
+ seqnum (1),
+ expire (Seconds (10))
+{
+}
+
+void HwmpRtableTest::Test1 ()
+{
+ HwmpRtable::LookupResult correct (hop, iface, metric, seqnum);
+
+ // Reactive path
+ table->AddReactivePath (dst, hop, iface, metric, expire, seqnum);
+ NS_TEST_ASSERT (table->LookupReactive (dst) == correct);
+ table->DeleteReactivePath (dst);
+ NS_TEST_ASSERT (! table->LookupReactive (dst).IsValid ());
+
+ // Proactive
+ table->AddProactivePath (metric, dst, hop, iface, expire, seqnum);
+ NS_TEST_ASSERT (table->LookupProactive () == correct);
+ table->DeleteProactivePath (dst);
+ NS_TEST_ASSERT (! table->LookupProactive ().IsValid ());
+}
+
+void HwmpRtableTest::Test2 ()
+{
+ table->AddReactivePath (dst, hop, iface, metric, expire, seqnum);
+ table->AddProactivePath (metric, dst, hop, iface, expire, seqnum);
+}
+
+void HwmpRtableTest::Test3 ()
+{
+ // this is assumed to be called when path records are already expired
+ HwmpRtable::LookupResult correct (hop, iface, metric, seqnum);
+ NS_TEST_ASSERT (table->LookupReactiveExpired (dst) == correct);
+ NS_TEST_ASSERT (table->LookupProactiveExpired () == correct);
+
+ NS_TEST_ASSERT (! table->LookupReactive (dst).IsValid ());
+ NS_TEST_ASSERT (! table->LookupProactive ().IsValid ());
+}
+
+void HwmpRtableTest::Test4 ()
+{
+ // TODO: test AddPrecursor and GetPrecursors
+}
+
+bool HwmpRtableTest::RunTests ()
+{
+ table = CreateObject<HwmpRtable> ();
+
+ Simulator::Schedule (Seconds (0), & HwmpRtableTest::Test1, this);
+ Simulator::Schedule (Seconds (1), & HwmpRtableTest::Test2, this);
+ Simulator::Schedule (expire + Seconds (2), & HwmpRtableTest::Test3, this);
+ Simulator::Schedule (expire + Seconds (3), & HwmpRtableTest::Test4, this);
+
+ Simulator::Run ();
+ Simulator::Destroy ();
+
+ return result;
+}
+
+#endif // RUN_SELF_TESTS
+
+} //namespace dot11s
+} //namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/hwmp-rtable.h Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,147 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#ifndef HWMP_RTABLE_H
+#define HWMP_RTABLE_H
+
+#include <map>
+#include "ns3/nstime.h"
+#include "ns3/mac48-address.h"
+#include "ie-dot11s-perr.h"
+namespace ns3 {
+namespace dot11s {
+/**
+ * \ingroup dot11s
+ *
+ * \brief Routing table for HWMP -- 802.11s routing protocol
+ */
+class HwmpRtable : public Object
+{
+public:
+ /// Means all interfaces
+ const static uint32_t INTERFACE_ANY = 0xffffffff;
+ /// Maximum (the best?) path metric
+ const static uint32_t MAX_METRIC = 0xffffffff;
+
+ /// Route lookup result, return type of LookupXXX methods
+ struct LookupResult
+ {
+ Mac48Address retransmitter;
+ uint32_t ifIndex;
+ uint32_t metric;
+ uint32_t seqnum;
+
+ LookupResult(Mac48Address r = Mac48Address::GetBroadcast (),
+ uint32_t i = INTERFACE_ANY,
+ uint32_t m = MAX_METRIC,
+ uint32_t s = 0)
+ : retransmitter (r),
+ ifIndex (i),
+ metric (m),
+ seqnum (s)
+ {
+ }
+
+ /// True for valid route
+ bool IsValid() const;
+ /// Compare route lookup results, used by tests
+ bool operator==(const LookupResult & o) const;
+ };
+ /// Path precursor = {MAC, interface ID}
+ typedef std::vector<std::pair<uint32_t, Mac48Address> > PrecursorList;
+
+public:
+ static TypeId GetTypeId ();
+ HwmpRtable ();
+ ~HwmpRtable ();
+ void DoDispose ();
+
+ ///\name Add/delete paths
+ //\{
+ void AddReactivePath (
+ Mac48Address destination,
+ Mac48Address retransmitter,
+ uint32_t interface,
+ uint32_t metric,
+ Time lifetime,
+ uint32_t seqnum
+ );
+ void AddProactivePath (
+ uint32_t metric,
+ Mac48Address root,
+ Mac48Address retransmitter,
+ uint32_t interface,
+ Time lifetime,
+ uint32_t seqnum
+ );
+ void AddPrecursor (Mac48Address destination, uint32_t precursorInterface, Mac48Address precursorAddress);
+ PrecursorList GetPrecursors (Mac48Address destination);
+ void DeleteProactivePath ();
+ void DeleteProactivePath (Mac48Address root);
+ void DeleteReactivePath (Mac48Address destination);
+ //\}
+
+ ///\name Lookup
+ //\{
+ /// Lookup path to destination
+ LookupResult LookupReactive (Mac48Address destination);
+ /// Return all reactive paths, including expired
+ LookupResult LookupReactiveExpired (Mac48Address destination);
+ /// Find proactive path to tree root. Note that calling this method has side effect of deleting expired proactive path
+ LookupResult LookupProactive ();
+ /// Return all proactive paths, including expired
+ LookupResult LookupProactiveExpired ();
+ //\}
+
+ /// When peer link with a given MAC-address fails - it returns list of unreachable destination addresses
+ std::vector<IePerr::FailedDestination> GetUnreachableDestinations (Mac48Address peerAddress);
+
+private:
+ /// Route found in reactive mode
+ struct ReactiveRoute
+ {
+ Mac48Address retransmitter;
+ uint32_t interface;
+ uint32_t metric;
+ Time whenExpire;
+ uint32_t seqnum;
+ std::vector<std::pair<uint32_t, Mac48Address> > precursors;
+ };
+ /// Route fond in proactive mode
+ struct ProactiveRoute
+ {
+ Mac48Address root;
+ Mac48Address retransmitter;
+ uint32_t interface;
+ uint32_t metric;
+ Time whenExpire;
+ uint32_t seqnum;
+ std::vector<std::pair<uint32_t, Mac48Address> > precursors;
+ };
+
+ /// List of routes
+ std::map<Mac48Address, ReactiveRoute> m_routes;
+ /// Path to proactive tree root MP
+ ProactiveRoute m_root;
+};
+} //namespace dot11s
+} //namespace ns3
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/hwmp-tag.cc Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,154 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#include "hwmp-tag.h"
+
+namespace ns3 {
+namespace dot11s{
+
+NS_OBJECT_ENSURE_REGISTERED (HwmpTag);
+//Class HwmpTag:
+HwmpTag::HwmpTag ():
+ m_address (Mac48Address::GetBroadcast ()),
+ m_ttl (0),
+ m_metric (0),
+ m_seqno (0)
+{
+}
+
+HwmpTag::~HwmpTag ()
+{
+}
+
+void
+HwmpTag::SetAddress (Mac48Address retransmitter)
+{
+ m_address = retransmitter;
+}
+
+Mac48Address
+HwmpTag::GetAddress ()
+{
+ return m_address;
+}
+
+void
+HwmpTag::SetTtl (uint8_t ttl)
+{
+ m_ttl = ttl;
+}
+
+uint8_t
+HwmpTag::GetTtl ()
+{
+ return m_ttl;
+}
+
+void
+HwmpTag::SetMetric (uint32_t metric)
+{
+ m_metric = metric;
+}
+
+uint32_t
+HwmpTag::GetMetric ()
+{
+ return m_metric;
+}
+
+void
+HwmpTag::SetSeqno (uint32_t seqno)
+{
+ m_seqno = seqno;
+}
+
+uint32_t
+HwmpTag::GetSeqno ()
+{
+ return m_seqno;
+}
+
+TypeId
+HwmpTag::GetTypeId ()
+{
+ static TypeId tid = TypeId ("ns3::dot11s::HwmpTag")
+ .SetParent<Tag> ()
+ .AddConstructor<HwmpTag> ();
+ return tid;
+}
+
+TypeId
+HwmpTag::GetInstanceTypeId () const
+{
+ return GetTypeId ();
+}
+
+uint32_t
+HwmpTag::GetSerializedSize () const
+{
+ return
+ 6 //address
+ +1 //ttl
+ +4 //metric
+ +4; //seqno
+}
+
+void
+HwmpTag::Serialize (TagBuffer i) const
+{
+ uint8_t address[6];
+ int j;
+ m_address.CopyTo (address);
+ i.WriteU8 (m_ttl);
+ i.WriteU32 (m_metric);
+ i.WriteU32(m_seqno);
+ for (j = 0; j < 6; j ++)
+ i.WriteU8 (address[j]);
+}
+
+void
+HwmpTag::Deserialize (TagBuffer i)
+{
+ uint8_t address[6];
+ int j;
+ m_ttl = i.ReadU8 ();
+ m_metric = i.ReadU32 ();
+ m_seqno = i.ReadU32 ();
+ for (j = 0; j < 6; j ++)
+ address[j] = i.ReadU8 ();
+ m_address.CopyFrom (address);
+}
+
+void
+HwmpTag::Print (std::ostream &os) const
+{
+ os << "address=" << m_address;
+ os << "ttl=" << m_ttl;
+ os << "metrc=" << m_metric;
+ os << "seqno=" << m_seqno;
+}
+void
+HwmpTag::DecrementTtl ()
+{
+ m_ttl --;
+}
+} //namespace dot11s
+} //namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/hwmp-tag.h Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,78 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ * Aleksey Kovalenko <kovalenko@iitp.ru>
+ * Pavel Boyko <boyko@iitp.ru>
+ */
+
+
+#ifndef HWMP_TAG_H
+#define HWMP_TAG_H
+
+#include "ns3/tag.h"
+#include "ns3/object.h"
+#include "ns3/mac48-address.h"
+namespace ns3 {
+namespace dot11s {
+/**
+ * \ingroup dot11s
+ *
+ * \brief Hwmp tag implements interaction between HWMP
+ * protocol and MeshWifiMac
+ *
+ * \details Hwmp tag keeps the following:
+ * 1. When packet is passed from Hwmp to 11sMAC:
+ * - retransmitter address,
+ * - TTL value,
+ * 2. When packet is passed to Hwmp from 11sMAC:
+ * - lasthop address,
+ * - TTL value,
+ * - metric value (metric of link is recalculated
+ * at each packet, but routing table stores metric
+ * obtained during path discovery procedure)
+ */
+class HwmpTag : public Tag
+{
+public:
+ HwmpTag ();
+ ~HwmpTag ();
+ void SetAddress (Mac48Address retransmitter);
+ Mac48Address GetAddress ();
+ void SetTtl (uint8_t ttl);
+ uint8_t GetTtl ();
+ void SetMetric (uint32_t metric);
+ uint32_t GetMetric ();
+ void SetSeqno (uint32_t seqno);
+ uint32_t GetSeqno ();
+ void DecrementTtl ();
+
+ static TypeId GetTypeId ();
+ virtual TypeId GetInstanceTypeId () const;
+ virtual uint32_t GetSerializedSize () const;
+ virtual void Serialize (TagBuffer i) const;
+ virtual void Deserialize (TagBuffer i);
+ virtual void Print (std::ostream &os) const;
+private:
+ Mac48Address m_address;
+ uint8_t m_ttl;
+ uint32_t m_metric;
+ uint32_t m_seqno;
+};
+} //namespace dot11s
+} //namespace ns3
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-beacon-timing.cc Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,260 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#include "ie-dot11s-beacon-timing.h"
+#include "ns3/log.h"
+#include "ns3/test.h"
+#include "ns3/packet.h"
+namespace ns3 {
+namespace dot11s {
+/*******************************************
+ * IeBeaconTimingUnit
+ *******************************************/
+IeBeaconTimingUnit::IeBeaconTimingUnit ():
+ m_aid (0),
+ m_lastBeacon (0),
+ m_beaconInterval (0)
+{
+}
+
+void
+IeBeaconTimingUnit::SetAid (uint8_t aid)
+{
+ m_aid = aid;
+}
+
+void
+IeBeaconTimingUnit::SetLastBeacon (uint16_t lastBeacon)
+{
+ m_lastBeacon = lastBeacon;
+}
+
+void
+IeBeaconTimingUnit::SetBeaconInterval (uint16_t beaconInterval)
+{
+ m_beaconInterval = beaconInterval;
+}
+
+uint8_t
+IeBeaconTimingUnit::GetAid () const
+{
+ return m_aid;
+}
+
+uint16_t
+IeBeaconTimingUnit::GetLastBeacon () const
+{
+ return m_lastBeacon;
+}
+
+uint16_t
+IeBeaconTimingUnit::GetBeaconInterval () const
+{
+ return m_beaconInterval;
+}
+/*******************************************
+ * IeBeaconTiming
+ *******************************************/
+IeBeaconTiming::IeBeaconTiming ():
+ m_numOfUnits (0)
+{
+}
+
+IeBeaconTiming::NeighboursTimingUnitsList
+IeBeaconTiming::GetNeighboursTimingElementsList ()
+{
+ return m_neighbours;
+}
+
+void
+IeBeaconTiming::AddNeighboursTimingElementUnit (
+ uint16_t aid,
+ Time last_beacon, //MicroSeconds!
+ Time beacon_interval //MicroSeconds!
+)
+{
+ if (m_numOfUnits == 50)
+ return;
+ //Firs we lookup if this element already exists
+ for (NeighboursTimingUnitsList::const_iterator i = m_neighbours.begin (); i != m_neighbours.end(); i++)
+ if (
+ ((*i)->GetAid () == AidToU8(aid))
+ && ((*i)->GetLastBeacon () == TimestampToU16(last_beacon))
+ && ((*i)->GetBeaconInterval () == BeaconIntervalToU16(beacon_interval))
+ )
+ return;
+ Ptr<IeBeaconTimingUnit>new_element = Create<IeBeaconTimingUnit> ();
+ new_element->SetAid (AidToU8(aid));
+ new_element->SetLastBeacon (TimestampToU16(last_beacon));
+ new_element->SetBeaconInterval (BeaconIntervalToU16(beacon_interval));
+ m_neighbours.push_back (new_element);
+ m_numOfUnits++;
+}
+
+void
+IeBeaconTiming::DelNeighboursTimingElementUnit (
+ uint16_t aid,
+ Time last_beacon, //MicroSeconds!
+ Time beacon_interval //MicroSeconds!
+)
+{
+ for (NeighboursTimingUnitsList::iterator i = m_neighbours.begin (); i != m_neighbours.end(); i++)
+ if (
+ ((*i)->GetAid () == AidToU8(aid))
+ && ((*i)->GetLastBeacon () == TimestampToU16(last_beacon))
+ && ((*i)->GetBeaconInterval () == BeaconIntervalToU16(beacon_interval))
+ )
+ {
+ m_neighbours.erase (i);
+ m_numOfUnits--;
+ break;
+ }
+}
+
+void
+IeBeaconTiming::ClearTimingElement ()
+{
+ uint16_t to_delete = 0;
+ uint16_t i;
+ for (NeighboursTimingUnitsList::iterator j = m_neighbours.begin (); j != m_neighbours.end(); j++)
+ {
+ to_delete++;
+ (*j) = 0;
+ }
+ for (i = 0; i < to_delete; i ++)
+ m_neighbours.pop_back ();
+ m_neighbours.clear ();
+
+}
+
+uint8_t
+IeBeaconTiming::GetInformationSize () const
+{
+ return (5*m_numOfUnits);
+}
+
+void
+IeBeaconTiming::PrintInformation (std::ostream& os) const
+{
+ os <<"Number of units: " << (uint16_t)m_numOfUnits << "\n";
+ for (NeighboursTimingUnitsList::const_iterator j = m_neighbours.begin (); j != m_neighbours.end(); j++)
+ os<< "AID=" << (uint16_t)(*j)->GetAid () << ", Last beacon was at "
+ << (*j)->GetLastBeacon ()<<", with beacon interval " << (*j)->GetBeaconInterval () << "\n";
+}
+
+void
+IeBeaconTiming::SerializeInformation (Buffer::Iterator i) const
+{
+ for (NeighboursTimingUnitsList::const_iterator j = m_neighbours.begin (); j != m_neighbours.end(); j++)
+ {
+ i.WriteU8 ((*j)->GetAid ());
+ i.WriteHtonU16 ((*j)->GetLastBeacon ());
+ i.WriteHtonU16 ((*j)->GetBeaconInterval ());
+ }
+}
+uint8_t
+IeBeaconTiming::DeserializeInformation (Buffer::Iterator start, uint8_t length)
+{
+ Buffer::Iterator i = start;
+ m_numOfUnits = length/5;
+ for (int j = 0; j < m_numOfUnits; j ++)
+ {
+ Ptr<IeBeaconTimingUnit> new_element = Create<IeBeaconTimingUnit> ();
+ new_element->SetAid (i.ReadU8());
+ new_element->SetLastBeacon (i.ReadNtohU16());
+ new_element->SetBeaconInterval (i.ReadNtohU16());
+ m_neighbours.push_back (new_element);
+ }
+ return i.GetDistanceFrom (start);
+};
+
+uint16_t
+IeBeaconTiming::TimestampToU16 (Time x)
+{
+ return ((uint16_t) ((x.GetMicroSeconds() >> 8)&0xffff));
+};
+
+uint16_t
+IeBeaconTiming::BeaconIntervalToU16 (Time x)
+{
+ return ((uint16_t) (x.GetMicroSeconds() >>10)&0xffff);
+};
+
+uint8_t
+IeBeaconTiming::AidToU8 (uint16_t x)
+{
+ return (uint8_t) (x&0xff);
+};
+
+bool operator== (const IeBeaconTimingUnit & a, const IeBeaconTimingUnit & b)
+{
+ return (
+ (a.GetAid () == b.GetAid ()) &&
+ (a.GetLastBeacon () == b.GetLastBeacon()) &&
+ (a.GetBeaconInterval () == b.GetBeaconInterval ())
+ );
+}
+bool operator== (const IeBeaconTiming & a, const IeBeaconTiming& b)
+{
+ if(a.m_numOfUnits != b.m_numOfUnits)
+ return false;
+ for(unsigned int i = 0; i < a.m_neighbours.size (); i ++)
+ if(!(*PeekPointer(a.m_neighbours[i]) == *PeekPointer(b.m_neighbours[i])))
+ return false;
+ return true;
+}
+
+#ifdef RUN_SELF_TESTS
+struct IeBeaconTimingBist : public Test
+{
+ IeBeaconTimingBist () : Test ("Mesh/802.11s/IE/BeaconTiming") {}
+ virtual bool RunTests();
+};
+
+/// Test instance
+static IeBeaconTimingBist g_IePerrBist;
+
+bool IeBeaconTimingBist::RunTests ()
+{
+ bool result(true);
+ // create test information element
+ IeBeaconTiming a;
+ a.IeBeaconTiming::AddNeighboursTimingElementUnit (1,Seconds(1.0), Seconds(4.0));
+ a.IeBeaconTiming::AddNeighboursTimingElementUnit (2,Seconds(2.0), Seconds(3.0));
+ a.IeBeaconTiming::AddNeighboursTimingElementUnit (3,Seconds(3.0), Seconds(2.0));
+ a.IeBeaconTiming::AddNeighboursTimingElementUnit (4,Seconds(4.0), Seconds(1.0));
+ Ptr<Packet> packet = Create<Packet> ();
+ packet->AddHeader(a);
+ IeBeaconTiming b;
+ packet->RemoveHeader(b);
+ NS_TEST_ASSERT_EQUAL (a, b);
+ //Test Find First
+ packet->AddHeader (a);
+ IeBeaconTiming c;
+ bool ok = c.FindFirst(packet);
+ NS_TEST_ASSERT (ok);
+ NS_TEST_ASSERT_EQUAL (a, c);
+ return result;
+}
+#endif
+} // namespace dot11s
+} //namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-beacon-timing.h Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,118 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#ifndef WIFI_TIMING_ELEMENT_H
+#define WIFI_TIMING_ELEMENT_H
+
+#include <vector>
+#include "ns3/nstime.h"
+#include "ns3/wifi-information-element.h"
+
+namespace ns3 {
+namespace dot11s {
+/**
+ * \ingroup dot11s
+ * \brief Describes one unit of beacon timing element
+ */
+class IeBeaconTimingUnit : public RefCountBase
+{
+public:
+ IeBeaconTimingUnit ();
+ void SetAid (uint8_t aid);
+ void SetLastBeacon (uint16_t last_beacon);
+ void SetBeaconInterval (uint16_t beacon_interval);
+
+ uint8_t GetAid () const;
+ uint16_t GetLastBeacon () const;
+ uint16_t GetBeaconInterval () const;
+ /**
+ * \brief Least significant octet of AID:
+ */
+ uint8_t m_aid;
+ /**
+ * \brief Last time we received a beacon in accordance with a
+ * local TSF measured in 256 microseconds unit:
+ */
+ uint16_t m_lastBeacon;
+ /**
+ * \brief Beacon interval of remote mesh point:
+ */
+ uint16_t m_beaconInterval;
+ friend bool operator== (const IeBeaconTimingUnit & a, const IeBeaconTimingUnit & b);
+};
+
+/**
+ * \ingroup dot11s
+ * \brief See 7.3.2.89 of 802.11s draft 2.07
+ */
+class IeBeaconTiming : public WifiInformationElement
+{
+public:
+ /**
+ * \ingroup dot11s
+ * This type is a list of timing elements obtained from neigbours with their beacons:
+ */
+ typedef std::vector< Ptr<IeBeaconTimingUnit> > NeighboursTimingUnitsList;
+
+ IeBeaconTiming ();
+ /**
+ * This methods are needed for beacon collision
+ * avoidance module:
+ */
+ NeighboursTimingUnitsList GetNeighboursTimingElementsList ();
+ void AddNeighboursTimingElementUnit (
+ uint16_t aid,
+ Time last_beacon,
+ Time beacon_interval
+ );
+ void DelNeighboursTimingElementUnit (
+ uint16_t aid,
+ Time last_beacon,
+ Time beacon_interval
+ );
+ void ClearTimingElement ();
+private:
+ WifiElementId ElementId () const {
+ return IE11S_BEACON_TIMING;
+ }
+ uint8_t GetInformationSize () const;
+ void SerializeInformation (Buffer::Iterator i) const;
+ uint8_t DeserializeInformation (Buffer::Iterator i, uint8_t length);
+ void PrintInformation (std::ostream& os) const;
+ /**
+ * Converters:
+ */
+ static uint16_t TimestampToU16 (Time x);
+ static uint16_t BeaconIntervalToU16 (Time x);
+ static uint8_t AidToU8 (uint16_t x);
+
+ NeighboursTimingUnitsList m_neighbours;
+ /**
+ * Timing element parameters:
+ */
+ uint16_t m_numOfUnits;
+ friend bool operator== (const IeBeaconTiming & a, const IeBeaconTiming & b);
+};
+bool operator== (const IeBeaconTiming & a, const IeBeaconTiming & b);
+bool operator== (const IeBeaconTimingUnit & a, const IeBeaconTimingUnit & b);
+} // namespace dot11s
+} //namespace ns3
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-configuration.cc Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,230 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ * Aleksey Kovalenko <kovalenko@iitp.ru>
+ */
+
+
+#include "ie-dot11s-configuration.h"
+#include "ns3/test.h"
+#include "ns3/packet.h"
+namespace ns3 {
+namespace dot11s {
+
+dot11sMeshCapability::dot11sMeshCapability ():
+ acceptPeerLinks (true),
+ MDAEnabled (false),
+ forwarding (true),
+ beaconTimingReport (true),
+ TBTTAdjustment (true),
+ powerSaveLevel (false)
+{}
+
+uint8_t dot11sMeshCapability::GetSerializedSize () const
+{
+ return 2;
+}
+
+Buffer::Iterator dot11sMeshCapability::Serialize (Buffer::Iterator i) const
+{
+ uint16_t result = 0;
+ if (acceptPeerLinks)
+ result |= 1 << 0;
+ if (MDAEnabled)
+ result |= 1 << 1;
+ if (forwarding)
+ result |= 1 << 2;
+ if (beaconTimingReport)
+ result |= 1 << 3;
+ if (TBTTAdjustment)
+ result |= 1 << 4;
+ if (powerSaveLevel)
+ result |= 1 << 5;
+ i.WriteHtonU16 (result);
+ return i;
+}
+
+Buffer::Iterator dot11sMeshCapability::Deserialize (Buffer::Iterator i)
+{
+ uint16_t cap = i.ReadNtohU16 ();
+ acceptPeerLinks = Is (cap, 0);
+ MDAEnabled = Is (cap, 1);
+ forwarding = Is (cap, 2);
+ beaconTimingReport = Is (cap, 3);
+ TBTTAdjustment = Is (cap, 4);
+ powerSaveLevel = Is (cap, 5);
+ return i;
+}
+
+bool dot11sMeshCapability::Is (uint16_t cap, uint8_t n) const
+{
+ uint16_t mask = 1<<n;
+ return (cap & mask) == mask;
+}
+
+IeConfiguration::IeConfiguration ():
+ m_APSId (PROTOCOL_HWMP),
+ m_APSMId (METRIC_AIRTIME),
+ m_CCMId (CONGESTION_DEFAULT),
+ m_CP (CHANNEL_PRECEDENCE_OFF)
+{}
+
+TypeId
+IeConfiguration::GetTypeId ()
+{
+ static TypeId tid = TypeId ("ns3::dot11s::IeConfiguration")
+ .SetParent<WifiInformationElement> ();
+ return tid;
+}
+
+TypeId
+IeConfiguration::GetInstanceTypeId () const
+{
+ return GetTypeId ();
+}
+uint8_t
+IeConfiguration::GetInformationSize () const
+{
+ return 1 // Version
+ + 4 // APSPId
+ + 4 // APSMId
+ + 4 // CCMId
+ + 4 // CP
+ + m_meshCap.GetSerializedSize ();
+}
+
+void
+IeConfiguration::SerializeInformation (Buffer::Iterator i) const
+{
+ i.WriteU8 (1); //Version
+ // Active Path Selection Protocol ID:
+ i.WriteHtonU32 (m_APSId);
+ // Active Path Metric ID:
+ i.WriteHtonU32 (m_APSMId);
+ // Congestion Control Mode ID:
+ i.WriteU32 (m_CCMId);
+ // Channel Precedence:
+ i.WriteU32 (m_CP);
+ m_meshCap.Serialize (i);
+}
+
+uint8_t
+IeConfiguration::DeserializeInformation (Buffer::Iterator i, uint8_t length)
+{
+ Buffer::Iterator start = i;
+ uint8_t version;
+ version = i.ReadU8 ();
+ // Active Path Selection Protocol ID:
+ m_APSId = (dot11sPathSelectionProtocol)i.ReadNtohU32 ();
+ // Active Path Metric ID:
+ m_APSMId = (dot11sPathSelectionMetric)i.ReadNtohU32 ();
+ // Congestion Control Mode ID:
+ m_CCMId = (dot11sCongestionControlMode)i.ReadU32 ();
+ // Channel Precedence:
+ m_CP = (dot11sChannelPrecedence)i.ReadU32 ();
+ i = m_meshCap.Deserialize (i);
+ return i.GetDistanceFrom (start);
+}
+void
+IeConfiguration::PrintInformation (std::ostream& os) const
+{
+ //TODO: print
+}
+void
+IeConfiguration::SetRouting (dot11sPathSelectionProtocol routingId)
+{
+ m_APSId = routingId;
+}
+
+void
+IeConfiguration::SetMetric (dot11sPathSelectionMetric metricId)
+{
+ m_APSMId = metricId;
+}
+
+bool
+IeConfiguration::IsHWMP ()
+{
+ return (m_APSId == PROTOCOL_HWMP);
+}
+
+bool
+IeConfiguration::IsAirtime ()
+{
+ return (m_APSMId == METRIC_AIRTIME);
+}
+
+dot11sMeshCapability const& IeConfiguration::MeshCapability ()
+{
+ return m_meshCap;
+}
+bool operator== (const dot11sMeshCapability & a, const dot11sMeshCapability & b)
+{
+ return (
+ (a.acceptPeerLinks == b.acceptPeerLinks) &&
+ (a.MDAEnabled == b.MDAEnabled) &&
+ (a.forwarding == b.forwarding) &&
+ (a.beaconTimingReport == b.beaconTimingReport) &&
+ (a.TBTTAdjustment == b.TBTTAdjustment) &&
+ (a.powerSaveLevel == b.powerSaveLevel)
+ );
+}
+bool operator== (const IeConfiguration & a, const IeConfiguration & b)
+{
+ return (
+ (a.m_APSId == b.m_APSId) &&
+ (a.m_APSMId == b.m_APSMId) &&
+ (a.m_CCMId == b.m_CCMId) &&
+ (a.m_CP == b.m_CP) &&
+ (a.m_meshCap == b.m_meshCap)
+ );
+}
+#ifdef RUN_SELF_TESTS
+
+/// Built-in self test for IePreq
+struct IeConfigurationBist : public Test
+{
+ IeConfigurationBist () : Test ("Mesh/802.11s/IE/Configuration") {}
+ virtual bool RunTests();
+};
+
+/// Test instance
+static IeConfigurationBist g_IeConfigurationBist;
+
+bool IeConfigurationBist::RunTests ()
+{
+ bool result(true);
+ IeConfiguration a;
+ Ptr<Packet> packet = Create<Packet> ();
+ packet->AddHeader (a);
+ IeConfiguration b;
+ packet->RemoveHeader (b);
+ NS_TEST_ASSERT_EQUAL (a, b);
+ // test FindFirst()
+ packet->AddHeader (a);
+ IeConfiguration c;
+ bool ok = c.FindFirst(packet);
+ NS_TEST_ASSERT (ok);
+ NS_TEST_ASSERT_EQUAL (a, c);
+
+ return result;
+}
+#endif
+} // namespace dot11s
+} //namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-configuration.h Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,130 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ * Aleksey Kovalenko <kovalenko@iitp.ru>
+ */
+
+
+#ifndef MESH_CONFIGURATION_H
+#define MESH_CONFIGURATION_H
+
+#include "ns3/wifi-information-element.h"
+
+namespace ns3 {
+namespace dot11s {
+/**
+ * \ingroup dot11s
+ * \brief See 7.3.2.81.1 in 802.11s draft 2.07
+ */
+enum dot11sPathSelectionProtocol
+{
+ PROTOCOL_HWMP = 0x000fac00,
+ PROTOCOL_NULL = 0x000facff,
+};
+/**
+ * \ingroup dot11s
+ * \brief See 7.3.2.81.2 in 802.11s draft 2.07
+ */
+enum dot11sPathSelectionMetric
+{
+ METRIC_AIRTIME = 0x000fac00,
+ METRIC_NULL = 0x000facff,
+};
+/**
+ * \ingroup dot11s
+ * \brief See 7.3.2.81.3 in 802.11s draft 2.07
+ */
+enum dot11sCongestionControlMode
+{
+ CONGESTION_DEFAULT = 0x000fac00,
+ CONGESTION_NULL = 0x000facff,
+};
+/**
+ * \ingroup dot11s
+ * \brief See 7.3.2.81.4 in 802.11s draft 2.07
+ */
+enum dot11sChannelPrecedence
+{
+ CHANNEL_PRECEDENCE_OFF = 0x000fac00,
+};
+
+/**
+ * \ingroup dot11s
+ * \brief See 7.3.2.81.5 in 802.11s draft 2.07
+ */
+class dot11sMeshCapability
+{
+public:
+ dot11sMeshCapability ();
+ uint8_t GetSerializedSize () const;
+ Buffer::Iterator Serialize (Buffer::Iterator i) const;
+ Buffer::Iterator Deserialize (Buffer::Iterator i);
+ bool acceptPeerLinks;
+ bool MDAEnabled;
+ bool forwarding;
+ bool beaconTimingReport;
+ bool TBTTAdjustment;
+ bool powerSaveLevel;
+ bool Is (uint16_t cap,uint8_t n) const;
+ friend bool operator== (const dot11sMeshCapability & a, const dot11sMeshCapability & b);
+};
+
+/**
+ * \ingroup dot11s
+ * \brief Describes Mesh Configuration Element
+ * see 7.3.2.81 of 802.11s draft 2.07
+ */
+class IeConfiguration : public WifiInformationElement
+{
+public:
+ static TypeId GetTypeId ();
+ TypeId GetInstanceTypeId () const;
+
+ IeConfiguration ();
+ void SetRouting (dot11sPathSelectionProtocol routingId);
+ void SetMetric (dot11sPathSelectionMetric metricId);
+ bool IsHWMP ();
+ bool IsAirtime ();
+
+ dot11sMeshCapability const& MeshCapability ();
+private:
+ WifiElementId ElementId () const
+ {
+ return IE11S_MESH_CONFIGURATION;
+ }
+ uint8_t GetInformationSize () const;
+ void SerializeInformation (Buffer::Iterator i) const;
+ uint8_t DeserializeInformation (Buffer::Iterator i, uint8_t length);
+ void PrintInformation (std::ostream& os) const;
+private:
+ /** Active Path Selection Protocol ID */
+ dot11sPathSelectionProtocol m_APSId;
+ /** Active Path Metric ID */
+ dot11sPathSelectionMetric m_APSMId;
+ /** Congestion Control Mode ID */
+ dot11sCongestionControlMode m_CCMId;
+ /* Channel Precedence */
+ dot11sChannelPrecedence m_CP;
+ dot11sMeshCapability m_meshCap;
+ friend bool operator== (const IeConfiguration & a, const IeConfiguration & b);
+};
+bool operator== (const IeConfiguration & a, const IeConfiguration & b);
+bool operator== (const dot11sMeshCapability & a, const dot11sMeshCapability & b);
+} // namespace dot11s
+} //namespace ns3
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-peer-management.cc Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,221 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ * Aleksey Kovalenko <kovalenko@iitp.ru>
+ */
+
+
+#include "ie-dot11s-peer-management.h"
+#include "ns3/assert.h"
+#include "ns3/test.h"
+#include "ns3/packet.h"
+
+namespace ns3 {
+namespace dot11s {
+
+IePeerManagement::IePeerManagement ():
+ m_length (0),
+ m_subtype (PEER_OPEN),
+ m_localLinkId (0),
+ m_peerLinkId (0),
+ m_reasonCode (REASON11S_RESERVED)
+{}
+
+
+void
+IePeerManagement::SetPeerOpen (uint16_t localLinkId)
+{
+ m_length = 3;
+ m_subtype = PEER_OPEN;
+ m_localLinkId = localLinkId;
+}
+void
+IePeerManagement::SetPeerClose (uint16_t localLinkId, uint16_t peerLinkId, PmpReasonCode reasonCode)
+{
+ m_length = 7;
+ m_subtype = PEER_CLOSE;
+ m_localLinkId = localLinkId;
+ m_peerLinkId = peerLinkId;
+ m_reasonCode = reasonCode;
+}
+
+void
+IePeerManagement::SetPeerConfirm (uint16_t localLinkId, uint16_t peerLinkId)
+{
+ m_length = 5;
+ m_subtype = PEER_CONFIRM;
+ m_localLinkId = localLinkId;
+ m_peerLinkId = peerLinkId;
+}
+
+PmpReasonCode
+IePeerManagement::GetReasonCode () const
+{
+ return m_reasonCode;
+}
+
+uint16_t
+IePeerManagement::GetLocalLinkId () const
+{
+ return m_localLinkId;
+}
+
+uint16_t
+IePeerManagement::GetPeerLinkId () const
+{
+ return m_peerLinkId;
+}
+
+uint8_t
+IePeerManagement::GetInformationSize (void) const
+{
+ return m_length;
+}
+
+bool
+IePeerManagement::SubtypeIsOpen () const
+{
+ return (m_subtype == PEER_OPEN);
+}
+bool
+IePeerManagement::SubtypeIsClose () const
+{
+ return (m_subtype == PEER_CLOSE);
+}
+bool
+IePeerManagement::SubtypeIsConfirm () const
+{
+ return (m_subtype == PEER_CONFIRM);
+}
+
+void
+IePeerManagement::SerializeInformation (Buffer::Iterator i) const
+{
+ i.WriteU8 (m_subtype);
+ i.WriteHtonU16 (m_localLinkId);
+ if (m_length > 3)
+ i.WriteHtonU16 (m_peerLinkId);
+ if (m_length > 5)
+ i.WriteHtonU16 (m_reasonCode);
+}
+uint8_t
+IePeerManagement::DeserializeInformation (Buffer::Iterator start, uint8_t length)
+{
+ Buffer::Iterator i = start;
+ m_subtype = i.ReadU8 ();
+ m_length = length;
+ if (m_subtype == PEER_OPEN)
+ {
+ NS_ASSERT (length == 3);
+ }
+ if (m_subtype == PEER_CONFIRM)
+ {
+ NS_ASSERT (length == 5);
+ }
+ if (m_subtype == PEER_CLOSE)
+ {
+ NS_ASSERT (length == 7);
+ }
+ m_localLinkId = i.ReadNtohU16 ();
+ if (m_length > 3)
+ m_peerLinkId = i.ReadNtohU16 ();
+ if (m_length > 5)
+ m_reasonCode = (PmpReasonCode)i.ReadNtohU16 ();
+ return i.GetDistanceFrom (start);
+}
+void
+IePeerManagement::PrintInformation (std::ostream& os) const
+{
+
+ os << " Subtype: = " << (uint16_t)m_subtype << "\n";
+ os << " Length: = " << (uint16_t)m_length << "\n";
+ os << " LocalLinkId: = " << m_localLinkId << "\n";
+ os << " PeerLinkId: = " << m_peerLinkId << "\n";
+ os << " ReasonCode: = " << m_reasonCode << "\n";
+}
+bool operator== (const IePeerManagement & a, const IePeerManagement & b)
+{
+ return (
+ (a.m_length == b.m_length) &&
+ (a.m_subtype == b.m_subtype) &&
+ (a.m_localLinkId == b.m_localLinkId) &&
+ (a.m_peerLinkId == b.m_peerLinkId) &&
+ (a.m_reasonCode == b.m_reasonCode)
+ );
+}
+#ifdef RUN_SELF_TESTS
+struct IePeerManagementBist : public Test
+{
+ IePeerManagementBist () : Test ("Mesh/802.11s/IE/PeerManagement") {}
+ virtual bool RunTests();
+};
+
+/// Test instance
+static IePeerManagementBist g_IePerrBist;
+
+bool IePeerManagementBist::RunTests ()
+{
+ bool result(true);
+ {
+ IePeerManagement a;
+ a.SetPeerOpen (1);
+ Ptr<Packet> packet = Create<Packet> ();
+ packet->AddHeader(a);
+ IePeerManagement b;
+ packet->RemoveHeader(b);
+ NS_TEST_ASSERT_EQUAL (a, b);
+ packet->AddHeader (a);
+ IePeerManagement c;
+ bool ok = c.FindFirst(packet);
+ NS_TEST_ASSERT (ok);
+ NS_TEST_ASSERT_EQUAL (a, c);
+ }
+ {
+ IePeerManagement a;
+ a.SetPeerConfirm (1,2);
+ Ptr<Packet> packet = Create<Packet> ();
+ packet->AddHeader(a);
+ IePeerManagement b;
+ packet->RemoveHeader(b);
+ NS_TEST_ASSERT_EQUAL (a, b);
+ packet->AddHeader (a);
+ IePeerManagement c;
+ bool ok = c.FindFirst(packet);
+ NS_TEST_ASSERT (ok);
+ NS_TEST_ASSERT_EQUAL (a, c);
+ }
+ {
+ IePeerManagement a;
+ a.SetPeerClose (1, 2, REASON11S_MESH_CONFIGURATION_POLICY_VIOLATION);
+ Ptr<Packet> packet = Create<Packet> ();
+ packet->AddHeader(a);
+ IePeerManagement b;
+ packet->RemoveHeader(b);
+ NS_TEST_ASSERT_EQUAL (a, b);
+ packet->AddHeader (a);
+ IePeerManagement c;
+ bool ok = c.FindFirst(packet);
+ NS_TEST_ASSERT (ok);
+ NS_TEST_ASSERT_EQUAL (a, c);
+ }
+ return result;
+}
+#endif
+} // namespace dot11s
+} //namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-peer-management.h Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,101 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ * Aleksey Kovalenko <kovalenko@iitp.ru>
+ */
+
+
+#ifndef MESH_PEER_MAN_ELEMENT
+#define MESH_PEER_MAN_ELEMENT
+
+#include "ns3/wifi-information-element.h"
+
+namespace ns3 {
+namespace dot11s {
+
+/**
+ * \ingroup dot11s
+ * \brief Codes used by 802.11s Peer Management Protocol
+ */
+enum PmpReasonCode {
+ REASON11S_PEER_LINK_CANCELLED,
+ REASON11S_MESH_MAX_PEERS,
+ REASON11S_MESH_CAPABILITY_POLICY_VIOLATION,
+ REASON11S_MESH_CLOSE_RCVD,
+ REASON11S_MESH_MAX_RETRIES,
+ REASON11S_MESH_CONFIRM_TIMEOUT,
+ REASON11S_MESH_SECURITY_ROLE_NEGOTIATION_DIFFERS,
+ REASON11S_MESH_SECURITY_AUTHENTICATION_IMPOSSIBLE,
+ REASON11S_MESH_SECURITY_FAILED_VERIFICATION,
+ REASON11S_MESH_INVALID_GTK,
+ REASON11S_MESH_MISMATCH_GTK,
+ REASON11S_MESH_INCONSISTENT_PARAMETERS,
+ REASON11S_MESH_CONFIGURATION_POLICY_VIOLATION,
+ REASON11S_RESERVED,
+};
+
+/**
+ * \ingroup dot11s
+ * \brief See 7.3.2.85 of draft 2.07
+ */
+class IePeerManagement : public WifiInformationElement
+{
+public:
+ IePeerManagement ();
+ enum Subtype {
+ PEER_OPEN = 0,
+ PEER_CLOSE = 1,
+ PEER_CONFIRM = 2,
+ };
+ void SetPeerOpen (uint16_t localLinkId);
+ void SetPeerClose (uint16_t localLinkID, uint16_t peerLinkId, PmpReasonCode reasonCode);
+ void SetPeerConfirm (uint16_t localLinkID, uint16_t peerLinkId);
+
+ PmpReasonCode GetReasonCode () const;
+ uint16_t GetLocalLinkId () const;
+ uint16_t GetPeerLinkId () const;
+ bool SubtypeIsOpen () const;
+ bool SubtypeIsClose () const;
+ bool SubtypeIsConfirm () const ;
+ uint8_t GetSubtype() const { return m_subtype;};
+private:
+ WifiElementId ElementId () const{
+ return IE11S_PEER_LINK_MANAGEMENT;
+ }
+ uint8_t GetInformationSize (void) const;
+ void SerializeInformation (Buffer::Iterator i) const;
+ uint8_t DeserializeInformation (Buffer::Iterator i, uint8_t length);
+ void PrintInformation (std::ostream& os) const;
+private:
+ uint8_t m_length;
+ uint8_t m_subtype;
+ uint16_t m_localLinkId;
+ /**
+ * Present within confirm and may be present in close
+ */
+ uint16_t m_peerLinkId;
+ /**
+ * Present only within close frame
+ */
+ PmpReasonCode m_reasonCode;
+ friend bool operator== (const IePeerManagement & a, const IePeerManagement & b);
+};
+bool operator== (const IePeerManagement & a, const IePeerManagement & b);
+} // namespace dot11s
+} //namespace ns3
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-perr.cc Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,207 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#include "ie-dot11s-perr.h"
+#include "ns3/address-utils.h"
+#include "ns3/node.h"
+#include "ns3/packet.h"
+#include "ns3/test.h"
+namespace ns3 {
+namespace dot11s {
+IePerr::~IePerr ()
+{
+}
+
+TypeId
+IePerr::GetTypeId ()
+{
+ static TypeId tid = TypeId ("ns3::dot11s::IePerr")
+ .SetParent<Object> ();
+ return tid;
+}
+void
+IePerr::PrintInformation (std::ostream &os) const
+{
+ // FILL
+}
+TypeId
+IePerr::GetInstanceTypeId () const
+{
+ return GetTypeId ();
+}
+IePerr::IePerr ():
+ m_numOfDest (0)
+{
+}
+uint8_t
+IePerr::GetNumOfDest ()
+{
+ return m_numOfDest;
+}
+void
+IePerr::SerializeInformation (Buffer::Iterator i) const
+{
+ i.WriteU8 (0);
+ i.WriteU8 (m_numOfDest);
+ NS_ASSERT (m_numOfDest == m_addressUnits.size ());
+ for (unsigned int j = 0; j < m_numOfDest; j++)
+ {
+ WriteTo (i, m_addressUnits[j].destination);
+ i.WriteHtonU32 (m_addressUnits[j].seqnum);
+ }
+}
+uint8_t
+IePerr::DeserializeInformation (Buffer::Iterator start, uint8_t length)
+{
+ Buffer::Iterator i = start;
+ i.Next (1); //Mode flags is not used now
+ m_numOfDest = i.ReadU8 ();
+ NS_ASSERT ((2+10*m_numOfDest) == length);
+ length = 0; //to avoid compiler warning in optimized builds
+ for (unsigned int j = 0; j < m_numOfDest; j++)
+ {
+ FailedDestination unit;
+ ReadFrom (i,unit.destination);
+ unit.seqnum = i.ReadNtohU32 ();
+ m_addressUnits.push_back (unit);
+ }
+ return i.GetDistanceFrom (start);
+}
+
+uint8_t
+IePerr::GetInformationSize () const
+{
+ uint8_t retval =
+ 1 //ModeFlags
+ +1 //NumOfDests
+ +6*m_numOfDest
+ +4*m_numOfDest;
+ return retval;
+}
+
+void
+IePerr::AddAddressUnit (FailedDestination unit)
+{
+ for (unsigned int i = 0; i < m_addressUnits.size (); i ++)
+ if (m_addressUnits[i].destination == unit.destination)
+ return;
+ m_addressUnits.push_back (unit);
+ m_numOfDest++;
+}
+
+std::vector<IePerr::FailedDestination>
+IePerr::GetAddressUnitVector () const
+{
+ return m_addressUnits;
+}
+void
+IePerr::DeleteAddressUnit (Mac48Address address)
+{
+ for (std::vector<FailedDestination>::iterator i = m_addressUnits.begin (); i != m_addressUnits.end(); i ++)
+ if (i->destination == address)
+ {
+ m_numOfDest --;
+ m_addressUnits.erase (i);
+ break;
+ }
+}
+void
+IePerr::Merge(const IePerr perr)
+{
+ std::vector<FailedDestination> to_merge = perr.GetAddressUnitVector ();
+ for (std::vector<FailedDestination>::iterator i = to_merge.begin (); i != to_merge.end(); i ++)
+ {
+ bool should_add = true;
+ for (std::vector<FailedDestination>::iterator j = m_addressUnits.begin (); j != m_addressUnits.end(); j ++)
+ if ((i->destination == j->destination) && (i->seqnum <= j->seqnum))
+ should_add = false;
+ if(should_add)
+ AddAddressUnit (*i);
+ }
+}
+void
+IePerr::ResetPerr ()
+{
+ m_numOfDest = 0;
+ m_addressUnits.clear ();
+}
+bool operator== (const IePerr & a, const IePerr & b)
+{
+ if(a.m_numOfDest != b.m_numOfDest)
+ return false;
+ for(unsigned int i = 0; i < a.m_addressUnits.size(); i ++)
+ {
+ if(a.m_addressUnits[i].destination != b.m_addressUnits[i].destination)
+ return false;
+ if(a.m_addressUnits[i].seqnum != b.m_addressUnits[i].seqnum)
+ return false;
+ }
+ return true;
+}
+#ifdef RUN_SELF_TESTS
+
+/// Built-in self test for IePreq
+struct IePerrBist : public Test
+{
+ IePerrBist () : Test ("Mesh/802.11s/IE/PERR") {}
+ virtual bool RunTests();
+};
+
+/// Test instance
+static IePerrBist g_IePerrBist;
+
+bool IePerrBist::RunTests ()
+{
+ bool result(true);
+ // create test information element
+ IePerr a;
+ IePerr::FailedDestination dest;
+ dest.destination = Mac48Address("11:22:33:44:55:66");
+ dest.seqnum = 1;
+ a.AddAddressUnit(dest);
+ dest.destination = Mac48Address("10:20:30:40:50:60");
+ dest.seqnum = 2;
+ a.AddAddressUnit(dest);
+ dest.destination = Mac48Address("01:02:03:04:05:06");
+ dest.seqnum = 3;
+ a.AddAddressUnit(dest);
+ Ptr<Packet> packet = Create<Packet> ();
+ packet->AddHeader (a);
+ IePerr b;
+ packet->RemoveHeader (b);
+ NS_TEST_ASSERT_EQUAL (a, b);
+ b.Merge(a);
+ NS_TEST_ASSERT_EQUAL (a, b);
+ // test FindFirst()
+ packet->AddHeader (a);
+ IePerr c;
+ bool ok = c.FindFirst(packet);
+ NS_TEST_ASSERT (ok);
+ NS_TEST_ASSERT_EQUAL (a, c);
+ return result;
+}
+
+#endif // RUN_SELF_TESTS
+
+} // namespace dot11s
+} //namespace ns3
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-perr.h Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#ifndef PERR_INFORMATION_ELEMENT_H
+#define PERR_INFORMATION_ELEMENT_H
+
+#include "ns3/mac48-address.h"
+#include "ns3/wifi-information-element.h"
+
+namespace ns3 {
+namespace dot11s {
+/**
+ * \ingroup dot11s
+ * \brief See 7.3.2.98 of 802.11s draft 2.07
+ */
+class IePerr : public WifiInformationElement
+{
+public:
+ IePerr ();
+ ~IePerr ();
+ static TypeId GetTypeId ();
+ virtual TypeId GetInstanceTypeId () const;
+ struct FailedDestination
+ {
+ Mac48Address destination;
+ uint32_t seqnum;
+ };
+ uint8_t GetNumOfDest ();
+
+ void AddAddressUnit (struct FailedDestination unit);
+ std::vector<FailedDestination> GetAddressUnitVector () const;
+ void DeleteAddressUnit (Mac48Address address);
+ void Merge(const IePerr perr);
+ void ResetPerr ();
+private:
+ WifiElementId ElementId () const{
+ return IE11S_PERR;
+ };
+ void SerializeInformation (Buffer::Iterator i) const;
+ uint8_t DeserializeInformation (Buffer::Iterator start, uint8_t length);
+ void PrintInformation (std::ostream& os) const;
+ uint8_t GetInformationSize () const;
+private:
+ uint8_t m_numOfDest;
+ std::vector<FailedDestination> m_addressUnits;
+ friend bool operator== (const IePerr & a, const IePerr & b);
+};
+ bool operator== (const IePerr & a, const IePerr & b);
+} // namespace dot11s
+} //namespace ns3
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-prep.cc Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,274 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#include "ie-dot11s-prep.h"
+#include "ns3/address-utils.h"
+#include "ns3/node.h"
+#include "ns3/assert.h"
+#include "ns3/test.h"
+#include "ns3/packet.h"
+namespace ns3 {
+namespace dot11s {
+/********************************
+ * IePrep
+ *******************************/
+IePrep::~IePrep ()
+{
+}
+
+TypeId
+IePrep::GetTypeId ()
+{
+ static TypeId tid = TypeId ("ns3::dot11s::IePrep")
+ .SetParent<Object> ();
+ return tid;
+}
+TypeId
+IePrep::GetInstanceTypeId () const
+{
+ return GetTypeId ();
+}
+IePrep::IePrep ():
+ m_flags (0),
+ m_hopcount (0),
+ m_ttl (0),
+ m_destinationAddress (Mac48Address::GetBroadcast()),
+ m_destSeqNumber (0),
+ m_lifetime (0),
+ m_metric (0),
+ m_originatorAddress (Mac48Address::GetBroadcast()),
+ m_originatorSeqNumber (0)
+{
+}
+void
+IePrep::SetFlags (uint8_t flags)
+{
+ m_flags = flags;
+}
+void
+IePrep::SetHopcount (uint8_t hopcount)
+{
+ m_hopcount = hopcount;
+}
+void
+IePrep::SetTtl (uint8_t ttl)
+{
+ m_ttl = ttl;
+}
+void
+IePrep::SetDestinationSeqNumber (uint32_t dest_seq_number)
+{
+ m_destSeqNumber = dest_seq_number;
+}
+void
+IePrep::SetDestinationAddress (Mac48Address dest_address)
+{
+ m_destinationAddress = dest_address;
+}
+void
+IePrep::SetMetric (uint32_t metric)
+{
+ m_metric = metric;
+}
+void
+IePrep::SetOriginatorAddress (Mac48Address originator_address)
+{
+ m_originatorAddress = originator_address;
+}
+void
+IePrep::SetOriginatorSeqNumber (uint32_t originator_seq_number)
+{
+ m_originatorSeqNumber = originator_seq_number;
+}
+void
+IePrep::SetLifetime (uint32_t lifetime)
+{
+ m_lifetime = lifetime;
+}
+uint8_t
+IePrep::GetFlags () const
+{
+ return m_flags;
+}
+uint8_t
+IePrep::GetHopcount () const
+{
+ return m_hopcount;
+}
+uint32_t
+IePrep::GetTtl () const
+{
+ return m_ttl;
+}
+uint32_t
+IePrep::GetDestinationSeqNumber () const
+{
+ return m_destSeqNumber;
+}
+Mac48Address
+IePrep::GetDestinationAddress () const
+{
+ return m_destinationAddress;
+}
+uint32_t
+IePrep::GetMetric () const
+{
+ return m_metric;
+}
+Mac48Address
+IePrep::GetOriginatorAddress () const
+{
+ return m_originatorAddress;
+}
+uint32_t
+IePrep::GetOriginatorSeqNumber () const
+{
+ return m_originatorSeqNumber;
+}
+uint32_t
+IePrep::GetLifetime () const
+{
+ return m_lifetime;
+}
+void
+IePrep::DecrementTtl ()
+{
+ m_ttl --;
+}
+
+void
+IePrep::IncrementMetric (uint32_t metric)
+{
+ m_metric +=metric;
+}
+
+
+void
+IePrep::SerializeInformation (Buffer::Iterator i) const
+{
+ i.WriteU8 (m_flags);
+ i.WriteU8 (m_hopcount);
+ i.WriteU8 (m_ttl);
+ WriteTo (i, m_destinationAddress);
+ i.WriteHtonU32 (m_destSeqNumber);
+ i.WriteHtonU32 (m_lifetime);
+ i.WriteHtonU32 (m_metric);
+ WriteTo (i, m_originatorAddress);
+ i.WriteHtonU32 (m_originatorSeqNumber);
+}
+uint8_t
+IePrep::DeserializeInformation (Buffer::Iterator start, uint8_t length)
+{
+ Buffer::Iterator i = start;
+ m_flags = i.ReadU8 ();
+ m_hopcount = i.ReadU8 ();
+ m_ttl = i.ReadU8 ();
+ ReadFrom (i, m_destinationAddress);
+ m_destSeqNumber = i.ReadNtohU32 ();
+ m_lifetime = i.ReadNtohU32 ();
+ m_metric = i.ReadNtohU32 ();
+ ReadFrom (i, m_originatorAddress);
+ m_originatorSeqNumber = i.ReadNtohU32 ();
+ return i.GetDistanceFrom (start);
+}
+uint8_t
+IePrep::GetInformationSize () const
+{
+ uint32_t retval =
+ 1 //Flags
+ +1 //Hopcount
+ +1 //Ttl
+ +6 //Dest address
+ +4 //Dest seqno
+ +4 //Lifetime
+ +4 //metric
+ +6 //Originator address
+ +4 //Originator seqno
+ +1; //destination count
+ return retval;
+};
+void
+IePrep::PrintInformation (std::ostream& os) const
+{
+ //TODO
+}
+bool operator== (const IePrep & a, const IePrep & b)
+{
+ return (
+ (a.m_flags == b.m_flags) &&
+ (a.m_hopcount == b.m_hopcount) &&
+ (a.m_ttl == b.m_ttl) &&
+ (a.m_destinationAddress == b.m_destinationAddress) &&
+ (a.m_destSeqNumber == b.m_destSeqNumber) &&
+ (a.m_lifetime == b.m_lifetime) &&
+ (a.m_metric == b.m_metric) &&
+ (a.m_originatorAddress == b.m_originatorAddress) &&
+ (a.m_originatorSeqNumber == b.m_originatorSeqNumber)
+ );
+}
+
+#ifdef RUN_SELF_TESTS
+
+/// Built-in self test for IePrep
+struct IePrepBist : public Test
+{
+ IePrepBist () : Test ("Mesh/802.11s/IE/PREP") {};
+ virtual bool RunTests();
+};
+
+/// Test instance
+static IePrepBist g_IePrepBist;
+
+bool IePrepBist::RunTests ()
+{
+ bool result(true);
+
+ // create test information element
+ IePrep a;
+ a.SetFlags (12);
+ a.SetHopcount (11);
+ a.SetTtl (10);
+ a.SetDestinationAddress (Mac48Address("11:22:33:44:55:66"));
+ a.SetDestinationSeqNumber (123);
+ a.SetLifetime (5000);
+ a.SetMetric (4321);
+ a.SetOriginatorAddress (Mac48Address("33:00:22:00:11:00"));
+ a.SetOriginatorSeqNumber (666);
+ // test roundtrip serialization
+ Ptr<Packet> packet = Create<Packet> ();
+ packet->AddHeader (a);
+ IePrep b;
+ packet->RemoveHeader (b);
+ NS_TEST_ASSERT_EQUAL (a, b);
+ // test FindFirst()
+ packet->AddHeader (a);
+ IePrep c;
+ bool ok = c.FindFirst(packet);
+ NS_TEST_ASSERT (ok);
+ NS_TEST_ASSERT_EQUAL (a, c);
+ return result;
+}
+
+#endif // RUN_SELF_TESTS
+
+} // namespace dot11s
+} //namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-prep.h Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,88 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#ifndef WIFI_PREP_INFORMATION_ELEMENT_H
+#define WIFI_PREP_INFORMATION_ELEMENT_H
+
+
+#include "ns3/mac48-address.h"
+#include "ns3/wifi-information-element.h"
+
+namespace ns3 {
+namespace dot11s {
+/**
+ * \ingroup dot11s
+ * \brief See 7.3.2.97 of 802.11s draft 2.07
+ */
+class IePrep : public WifiInformationElement
+{
+public:
+ IePrep ();
+ ~IePrep ();
+ static TypeId GetTypeId ();
+ virtual TypeId GetInstanceTypeId () const;
+ void SetFlags (uint8_t flags);
+ void SetHopcount (uint8_t hopcount);
+ void SetTtl (uint8_t ttl);
+ void SetDestinationAddress (Mac48Address dest_address);
+ void SetDestinationSeqNumber (uint32_t dest_seq_number);
+ void SetLifetime (uint32_t lifetime);
+ void SetMetric (uint32_t metric);
+ void SetOriginatorAddress (Mac48Address originator_address);
+ void SetOriginatorSeqNumber (uint32_t originator_seq_number);
+
+ uint8_t GetFlags () const;
+ uint8_t GetHopcount () const;
+ uint32_t GetTtl () const;
+ Mac48Address GetDestinationAddress () const;
+ uint32_t GetDestinationSeqNumber () const;
+ uint32_t GetLifetime () const;
+ uint32_t GetMetric () const;
+ Mac48Address GetOriginatorAddress () const;
+ uint32_t GetOriginatorSeqNumber ()const ;
+
+ void DecrementTtl ();
+ void IncrementMetric (uint32_t metric);
+private:
+ WifiElementId ElementId () const{
+ return IE11S_PREP;
+ }
+ void SerializeInformation (Buffer::Iterator i) const;
+ uint8_t DeserializeInformation (Buffer::Iterator start, uint8_t length);
+ uint8_t GetInformationSize () const;
+ void PrintInformation (std::ostream& os) const;
+private:
+ uint8_t m_flags;
+ uint8_t m_hopcount;
+ uint8_t m_ttl;
+ Mac48Address m_destinationAddress;
+ uint32_t m_destSeqNumber;
+ uint32_t m_lifetime;
+ uint32_t m_metric;
+ Mac48Address m_originatorAddress;
+ uint32_t m_originatorSeqNumber;
+ friend bool operator== (const IePrep & a, const IePrep & b);
+};
+bool operator== (const IePrep & a, const IePrep & b);
+} // namespace dot11s
+} //namespace ns3
+#endif
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-preq.cc Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,481 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#include "ie-dot11s-preq.h"
+#include "ns3/address-utils.h"
+#include "ns3/node.h"
+#include "ns3/assert.h"
+#include "ns3/test.h"
+#include "ns3/packet.h"
+
+namespace ns3 {
+namespace dot11s {
+/*************************
+ * DestinationAddressUnit
+ ************************/
+DestinationAddressUnit::DestinationAddressUnit ():
+ m_do (false),
+ m_rf (false),
+ m_usn (false),
+ m_destinationAddress (Mac48Address ()),
+ m_destSeqNumber (0)
+{
+}
+void
+DestinationAddressUnit::SetFlags (bool doFlag, bool rfFlag, bool usnFlag)
+{
+ m_do = doFlag;
+ m_rf = rfFlag;
+ m_usn = usnFlag;
+}
+
+void
+DestinationAddressUnit::SetDestSeqNumber (uint32_t dest_seq_number)
+{
+ m_destSeqNumber = dest_seq_number;
+ if(m_destSeqNumber != 0)
+ m_usn = true;
+}
+void
+DestinationAddressUnit::SetDestinationAddress (Mac48Address dest_address)
+{
+ m_destinationAddress = dest_address;
+}
+bool
+DestinationAddressUnit::IsDo ()
+{
+ return m_do;
+}
+
+bool
+DestinationAddressUnit::IsRf ()
+{
+ return m_rf;
+}
+bool
+DestinationAddressUnit::IsUsn ()
+{
+ return m_usn;
+}
+uint32_t
+DestinationAddressUnit::GetDestSeqNumber () const
+{
+ return m_destSeqNumber;
+}
+Mac48Address
+DestinationAddressUnit::GetDestinationAddress () const
+{
+ return m_destinationAddress;
+}
+/********************************
+ * IePreq
+ *******************************/
+IePreq::~IePreq ()
+{
+}
+
+TypeId
+IePreq::GetTypeId ()
+{
+ static TypeId tid = TypeId ("ns3::dot11s::IePreq")
+ .SetParent<Object> ();
+ return tid;
+}
+TypeId
+IePreq::GetInstanceTypeId () const
+{
+ return GetTypeId ();
+}
+
+IePreq::IePreq ():
+ m_maxSize (32),
+ m_flags (0),
+ m_hopCount (0),
+ m_ttl (0),
+ m_preqId (0),
+ m_originatorAddress (Mac48Address::GetBroadcast()),
+ m_originatorSeqNumber (0),
+ m_lifetime (0),
+ m_metric (0),
+ m_destCount (0)
+{
+}
+void
+IePreq::SetUnicastPreq ()
+{
+ m_flags |= 1<<1;
+}
+
+void
+IePreq::SetNeedNotPrep ()
+{
+ m_flags |= 1<<2;
+}
+//void
+//IePreq::SetFlags (uint8_t flags)
+//{
+// m_flags = flags;
+//}
+void
+IePreq::SetHopcount (uint8_t hopcount)
+{
+ m_hopCount = hopcount;
+}
+void
+IePreq::SetTTL (uint8_t ttl)
+{
+ m_ttl = ttl;
+}
+void
+IePreq::SetPreqID (uint32_t preq_id)
+{
+ m_preqId = preq_id;
+}
+void
+IePreq::SetMetric (uint32_t metric)
+{
+ m_metric = metric;
+}
+void
+IePreq::SetOriginatorAddress (Mac48Address originator_address)
+{
+ m_originatorAddress = originator_address;
+}
+void
+IePreq::SetOriginatorSeqNumber (uint32_t originator_seq_number)
+{
+ m_originatorSeqNumber = originator_seq_number;
+}
+void
+IePreq::SetLifetime (uint32_t lifetime)
+{
+ m_lifetime = lifetime;
+}
+void
+IePreq::SetDestCount (uint8_t dest_count)
+{
+ m_destCount = dest_count;
+}
+bool
+IePreq::IsUnicastPreq () const
+{
+ return (m_flags & (1<<1));
+}
+bool
+IePreq::IsNeedNotPrep () const
+{
+ return (m_flags & (1<<2));
+}
+uint8_t
+IePreq::GetHopCount () const
+{
+ return m_hopCount;
+}
+uint8_t
+IePreq::GetTtl () const
+{
+ return m_ttl;
+}
+uint32_t
+IePreq::GetPreqID () const
+{
+ return m_preqId;
+}
+uint32_t
+IePreq::GetMetric () const
+{
+ return m_metric;
+}
+Mac48Address
+IePreq::GetOriginatorAddress () const
+{
+ return m_originatorAddress;
+}
+uint32_t
+IePreq::GetOriginatorSeqNumber () const
+{
+ return m_originatorSeqNumber;
+}
+uint32_t
+IePreq::GetLifetime () const
+{
+ return m_lifetime;
+}
+
+uint8_t
+IePreq::GetDestCount () const
+{
+ return m_destCount;
+}
+void
+IePreq::DecrementTtl ()
+{
+ m_ttl --;
+ m_hopCount ++;
+}
+void
+IePreq::IncrementMetric (uint32_t metric)
+{
+ m_metric +=metric;
+}
+void
+IePreq::SerializeInformation (Buffer::Iterator i) const
+{
+ i.WriteU8 (m_flags);
+ i.WriteU8 (m_hopCount);
+ i.WriteU8 (m_ttl);
+ i.WriteHtonU32 (m_preqId);
+ WriteTo (i, m_originatorAddress);
+ i.WriteHtonU32 (m_originatorSeqNumber);
+ i.WriteHtonU32 (m_lifetime);
+ i.WriteHtonU32 (m_metric);
+ i.WriteU8 (m_destCount);
+ int written = 0;
+ for (std::vector<Ptr<DestinationAddressUnit> >::const_iterator j = m_destinations.begin (); j != m_destinations.end(); j++)
+ {
+ uint8_t flags = 0;
+ if ((*j)->IsDo ())
+ flags += 128;
+ if ((*j)->IsRf ())
+ flags += 64;
+ if((*j)->IsUsn ())
+ flags += 32;
+ i.WriteU8 (flags);
+ WriteTo (i, (*j)->GetDestinationAddress());
+ i.WriteHtonU32 ((*j)->GetDestSeqNumber ());
+ written++;
+ if (written > m_maxSize)
+ break;
+ }
+}
+uint8_t
+IePreq::DeserializeInformation (Buffer::Iterator start, uint8_t length)
+{
+ Buffer::Iterator i = start;
+ m_flags = i.ReadU8 ();
+ m_hopCount = i.ReadU8 ();
+ m_ttl = i.ReadU8 ();
+ m_preqId = i.ReadNtohU32 ();
+ ReadFrom (i, m_originatorAddress);
+ m_originatorSeqNumber = i.ReadNtohU32 ();
+ m_lifetime = i.ReadNtohU32 ();
+ m_metric = i.ReadNtohU32 ();
+ m_destCount = i.ReadU8 ();
+ for (int j = 0; j < m_destCount; j++ )
+ {
+ Ptr<DestinationAddressUnit> new_element = Create<DestinationAddressUnit> ();
+ bool doFlag = false;
+ bool rfFlag = false;
+ bool usnFlag = false;
+ uint8_t flags = i.ReadU8 ();
+ if (flags >= 128)
+ {
+ doFlag = true;
+ flags -=128;
+ }
+ if (flags >=64)
+ {
+ rfFlag = true;
+ flags -= 64;
+ }
+ if (flags >= 32)
+ usnFlag = true;
+ new_element->SetFlags (doFlag, rfFlag, usnFlag);
+ Mac48Address addr;
+ ReadFrom (i,addr);
+ new_element->SetDestinationAddress (addr);
+ new_element->SetDestSeqNumber (i.ReadNtohU32());
+ m_destinations.push_back (new_element);
+ NS_ASSERT (28+j*11 < length);
+ }
+ return i.GetDistanceFrom (start);
+}
+uint8_t
+IePreq::GetInformationSize () const
+{
+ uint8_t retval =
+ 1 //Flags
+ +1 //Hopcount
+ +1 //TTL
+ +4 //PREQ ID
+ +6 //Source address (originator)
+ +4 //Originator seqno
+ +4 //Lifetime
+ +4 //metric
+ +1; //destination count
+ if (m_destCount > m_maxSize)
+ retval += (m_maxSize*11);
+ else
+ retval += (m_destCount*11);
+ return retval;
+}
+void
+IePreq::PrintInformation (std::ostream &os) const
+{
+ os << " originator address = " << m_originatorAddress << "\n";
+ os << " TTL = " << (uint16_t)m_ttl << "\n";
+ os << " hop count = " << (uint16_t)m_hopCount << "\n";
+ os << " metric = " << m_metric << "\n";
+ os << " seqno = " << m_originatorSeqNumber << "\n";
+ os << " lifetime = " << m_lifetime << "\n";
+ os << " preq ID = " <<m_preqId << "\n";
+ os << " Destinations are:\n";
+ for (int j = 0; j < m_destCount; j++ )
+ os << " " << m_destinations[j]->GetDestinationAddress () << "\n";
+}
+std::vector<Ptr<DestinationAddressUnit> >
+IePreq::GetDestinationList ()
+{
+ return m_destinations;
+}
+void
+IePreq::AddDestinationAddressElement (
+ bool doFlag, bool rfFlag,
+ Mac48Address dest_address,
+ uint32_t dest_seq_number
+)
+{
+ for (std::vector<Ptr<DestinationAddressUnit> >::const_iterator i = m_destinations.begin (); i != m_destinations.end(); i++ )
+ if ((*i)->GetDestinationAddress () == dest_address)
+ return;
+ Ptr<DestinationAddressUnit>new_element = Create<DestinationAddressUnit> ();
+ new_element->SetFlags (doFlag, rfFlag, false);
+ new_element->SetDestinationAddress (dest_address);
+ new_element->SetDestSeqNumber (dest_seq_number);
+ m_destinations.push_back (new_element);
+ m_destCount++;
+}
+void
+IePreq::DelDestinationAddressElement (Mac48Address dest_address)
+{
+ for (std::vector<Ptr<DestinationAddressUnit> >::iterator i = m_destinations.begin (); i != m_destinations.end(); i++)
+ if ((*i)->GetDestinationAddress () == dest_address)
+ {
+ m_destinations.erase (i);
+ m_destCount--;
+ break;
+ }
+}
+void
+IePreq::ClearDestinationAddressElement ()
+{
+ int i;
+ for (std::vector<Ptr<DestinationAddressUnit> >::iterator j = m_destinations.begin (); j != m_destinations.end(); j++)
+ (*j) = 0;
+ for (i = 0; i < m_destCount; i ++)
+ m_destinations.pop_back ();
+ m_destinations.clear ();
+}
+bool operator== (const DestinationAddressUnit & a, const DestinationAddressUnit & b)
+{
+ return (a.m_do == b.m_do
+ && a.m_rf == b.m_rf
+ && a.m_usn == b.m_usn
+ && a.m_destinationAddress == b.m_destinationAddress
+ && a.m_destSeqNumber == b.m_destSeqNumber
+ );
+}
+bool operator== (const IePreq & a, const IePreq & b)
+{
+ bool ok = ( a.m_flags == b.m_flags
+ && a.m_hopCount == b.m_hopCount
+ && a.m_ttl == b.m_ttl
+ && a.m_preqId == b.m_preqId
+ && a.m_originatorAddress == b.m_originatorAddress
+ && a.m_originatorSeqNumber == b.m_originatorSeqNumber
+ && a.m_lifetime == b.m_lifetime
+ && a.m_metric == b.m_metric
+ && a.m_destCount == b.m_destCount
+ );
+
+ if (! ok)
+ return false;
+
+ if (a.m_destinations.size() != b.m_destinations.size())
+ return false;
+
+ for (size_t i = 0; i < a.m_destinations.size(); ++i)
+ if (!( *(PeekPointer (a.m_destinations[i])) ==
+ *(PeekPointer (b.m_destinations[i]))
+ )
+ )
+ return false;
+
+ return true;
+}
+bool
+IePreq::MayAddAddress (Mac48Address originator)
+{
+ if (m_originatorAddress != originator)
+ return false;
+ if(m_destinations[0]->GetDestinationAddress () == Mac48Address::GetBroadcast ())
+ return false;
+ return true;
+}
+#ifdef RUN_SELF_TESTS
+
+/// Built-in self test for IePreq
+struct IePreqBist : public Test
+{
+ IePreqBist () : Test ("Mesh/802.11s/IE/PREQ") {}
+ virtual bool RunTests();
+};
+
+/// Test instance
+static IePreqBist g_IePreqBist;
+
+bool IePreqBist::RunTests ()
+{
+ bool result(true);
+
+ // create test information element
+ IePreq a;
+ a.SetHopcount (0);
+ a.SetTTL (1);
+ a.SetPreqID (2);
+ a.SetOriginatorAddress ( Mac48Address("11:22:33:44:55:66") );
+ a.SetOriginatorSeqNumber (3);
+ a.SetLifetime (4);
+ a.AddDestinationAddressElement (false, false, Mac48Address("11:11:11:11:11:11"), 5);
+ a.AddDestinationAddressElement (false, false, Mac48Address("22:22:22:22:22:22"), 6);
+
+ // test roundtrip serialization
+ Ptr<Packet> packet = Create<Packet> ();
+ packet->AddHeader (a);
+ IePreq b;
+ packet->RemoveHeader (b);
+ NS_TEST_ASSERT_EQUAL (a, b);
+
+ // test FindFirst()
+ packet->AddHeader (a);
+ IePreq c;
+ bool ok = c.FindFirst(packet);
+ NS_TEST_ASSERT (ok);
+ NS_TEST_ASSERT_EQUAL (a, c);
+
+ return result;
+}
+
+#endif // RUN_SELF_TESTS
+
+} // namespace dot11s
+} //namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-preq.h Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,145 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#ifndef WIFI_PREQ_INFORMATION_ELEMENT_H
+#define WIFI_PREQ_INFORMATION_ELEMENT_H
+
+#include <vector>
+
+#include "ns3/mac48-address.h"
+#include "ns3/wifi-information-element.h"
+
+namespace ns3 {
+namespace dot11s {
+/**
+ * \ingroup dot11s
+ * \brief Describes an address unit in PREQ information element
+ * See 7.3.2.96 for more details
+ */
+class DestinationAddressUnit : public RefCountBase
+{
+public:
+ DestinationAddressUnit ();
+ void SetFlags (bool doFlag, bool rfFlag, bool usnFlag);
+ void SetDestinationAddress (Mac48Address dest_address);
+ void SetDestSeqNumber (uint32_t dest_seq_number);
+ bool IsDo ();
+ bool IsRf ();
+ bool IsUsn ();
+ Mac48Address GetDestinationAddress () const;
+ uint32_t GetDestSeqNumber () const;
+private:
+ bool m_do;
+ bool m_rf;
+ bool m_usn;
+ Mac48Address m_destinationAddress;
+ uint32_t m_destSeqNumber;
+
+ friend bool operator== (const DestinationAddressUnit & a, const DestinationAddressUnit & b);
+};
+/**
+ * \ingroup dot11s
+ * \brief See 7.3.2.96 of 802.11s draft 2.07
+ */
+class IePreq : public WifiInformationElement
+{
+public:
+ IePreq ();
+ ~IePreq ();
+ static TypeId GetTypeId ();
+ virtual TypeId GetInstanceTypeId () const;
+ void AddDestinationAddressElement (
+ bool doFlag,
+ bool rfFlag,
+ Mac48Address dest_address,
+ uint32_t dest_seq_number
+ );
+ void DelDestinationAddressElement (Mac48Address dest_address);
+ void ClearDestinationAddressElement ();
+ std::vector<Ptr<DestinationAddressUnit> > GetDestinationList ();
+ void SetUnicastPreq ();
+ /*
+ * \brief In proactive case: need we send PREP
+ */
+ void SetNeedNotPrep ();
+ void SetHopcount (uint8_t hopcount);
+ void SetTTL (uint8_t ttl);
+ void SetPreqID (uint32_t id);
+ void SetOriginatorAddress (Mac48Address originator_address);
+ void SetOriginatorSeqNumber (uint32_t originator_seq_number);
+ void SetLifetime (uint32_t lifetime);
+ void SetMetric (uint32_t metric);
+ void SetDestCount (uint8_t dest_count);
+
+ bool IsUnicastPreq () const;
+ bool IsNeedNotPrep () const;
+ uint8_t GetHopCount () const;
+ uint8_t GetTtl ()const ;
+ uint32_t GetPreqID () const;
+ Mac48Address GetOriginatorAddress () const;
+ uint32_t GetOriginatorSeqNumber () const;
+ uint32_t GetLifetime () const;
+ uint32_t GetMetric () const;
+ uint8_t GetDestCount () const;
+ void DecrementTtl ();
+ void IncrementMetric (uint32_t metric);
+ /*
+ * \brief Checks that preq's originator address equals to originator, and
+ * this preq is not proactive
+ */
+ bool MayAddAddress(Mac48Address originator);
+
+private:
+ WifiElementId ElementId () const{
+ return IE11S_PREQ;
+ }
+ void SerializeInformation (Buffer::Iterator i) const;
+ uint8_t DeserializeInformation (Buffer::Iterator i, uint8_t length);
+ uint8_t GetInformationSize () const;
+ void PrintInformation (std::ostream& os) const;
+ /**
+ * how many destinations we support
+ */
+ uint8_t m_maxSize; //TODO: make as an attrubute
+ /**
+ * Fields of information element:
+ */
+ uint8_t m_flags;
+ uint8_t m_hopCount;
+ uint8_t m_ttl;
+ uint32_t m_preqId;
+ Mac48Address m_originatorAddress;
+ uint32_t m_originatorSeqNumber;
+ uint32_t m_lifetime;
+ uint32_t m_metric;
+ uint8_t m_destCount;
+ std::vector<Ptr<DestinationAddressUnit> > m_destinations;
+
+ friend bool operator== (const IePreq & a, const IePreq & b);
+};
+
+bool operator== (const DestinationAddressUnit & a, const DestinationAddressUnit & b);
+bool operator== (const IePreq & a, const IePreq & b);
+
+} // namespace dot11s
+} //namespace ns3
+#endif
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-rann.cc Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,237 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#include "ie-dot11s-rann.h"
+#include "ns3/assert.h"
+#include "ns3/address-utils.h"
+#include "ns3/node.h"
+#include "ns3/packet.h"
+#include "ns3/test.h"
+
+namespace ns3 {
+namespace dot11s {
+
+IeRann::~IeRann ()
+{
+}
+TypeId
+IeRann::GetTypeId ()
+{
+ static TypeId tid = TypeId ("ns3::dot11s::IeRann").SetParent<Object> ();
+ return tid;
+}
+TypeId
+IeRann::GetInstanceTypeId () const
+{
+ return GetTypeId ();
+}
+IeRann::IeRann ():
+ m_flags (0),
+ m_hopcount (0),
+ m_ttl (0),
+ m_originatorAddress (Mac48Address::GetBroadcast()),
+ m_destSeqNumber (0),
+ m_metric (0)
+{
+}
+void
+IeRann::SetFlags (uint8_t flags)
+{
+ m_flags = flags;
+}
+void
+IeRann::SetHopcount (uint8_t hopcount)
+{
+ m_hopcount = hopcount;
+}
+void
+IeRann::SetTTL (uint8_t ttl)
+{
+ m_ttl = ttl;
+}
+void
+IeRann::SetDestSeqNumber (uint32_t dest_seq_number)
+{
+ m_destSeqNumber = dest_seq_number;
+}
+void
+IeRann::SetMetric (uint32_t metric)
+{
+ m_metric = metric;
+}
+void
+IeRann::SetOriginatorAddress (Mac48Address originator_address)
+{
+ m_originatorAddress = originator_address;
+}
+
+uint8_t
+IeRann::GetFlags ()
+{
+ return m_flags;
+}
+uint8_t
+IeRann::GetHopcount ()
+{
+ return m_hopcount;
+}
+uint8_t
+IeRann::GetTtl ()
+{
+ return m_ttl;
+}
+uint32_t
+IeRann::GetDestSeqNumber ()
+{
+ return m_destSeqNumber;
+}
+uint32_t
+IeRann::GetMetric ()
+{
+ return m_metric;
+}
+void
+IeRann::DecrementTtl ()
+{
+ m_ttl --;
+ m_hopcount ++;
+}
+
+void
+IeRann::IncrementMetric (uint32_t m)
+{
+ m_metric += m;
+}
+
+Mac48Address
+IeRann::GetOriginatorAddress ()
+{
+ return m_originatorAddress;
+}
+void
+IeRann::SerializeInformation (Buffer::Iterator i) const
+{
+ i.WriteU8 (m_flags);
+ i.WriteU8 (m_hopcount);
+ i.WriteU8 (m_ttl);
+ WriteTo (i, m_originatorAddress);
+ i.WriteHtonU32 (m_destSeqNumber);
+ i.WriteHtonU32 (m_metric);
+}
+uint8_t
+IeRann::DeserializeInformation (Buffer::Iterator start, uint8_t length)
+{
+ Buffer::Iterator i = start;
+ m_flags = i.ReadU8 ();
+ m_hopcount = i.ReadU8 ();
+ m_ttl = i.ReadU8 ();
+ ReadFrom (i, m_originatorAddress);
+ m_destSeqNumber = i.ReadNtohU32 ();
+ m_metric = i.ReadNtohU32 ();
+ return i.GetDistanceFrom (start);
+}
+uint8_t
+IeRann::GetInformationSize () const
+{
+ uint8_t retval =
+ 1 //Flags
+ +1 //Hopcount
+ +1 //TTL
+ +6 //OriginatorAddress
+ +4 //DestSeqNumber
+ +4;//Metric
+ return retval;
+}
+
+void
+IeRann::PrintInformation (std::ostream &os) const
+{
+ os << " flags = " << (int)m_flags << "\n";
+ os << " hop count = " << (int)m_hopcount << "\n";
+ os << " TTL = " << (int)m_ttl << "\n";
+ os << " originator address = " << m_originatorAddress<< "\n";
+ os << " dst seq. number = " << m_destSeqNumber << "\n";
+ os << " metric = " << m_metric << "\n";
+}
+
+bool
+operator== (const IeRann & a, const IeRann & b)
+{
+ return (a.m_flags == b.m_flags
+ && a.m_hopcount == b.m_hopcount
+ && a.m_ttl == b.m_ttl
+ && a.m_originatorAddress == b.m_originatorAddress
+ && a.m_destSeqNumber == b.m_destSeqNumber
+ && a.m_metric == b.m_metric
+ );
+}
+
+#ifdef RUN_SELF_TESTS
+
+/// Built-in self test for IeRann
+struct IeRannBist : public Test
+{
+ IeRannBist () : Test ("Mesh/802.11s/IE/RANN") {}
+ virtual bool RunTests();
+};
+
+/// Test instance
+static IeRannBist g_IeRannBist;
+
+bool IeRannBist::RunTests ()
+{
+ bool result(true);
+
+ // create test information element
+ IeRann a;
+
+ a.SetFlags (1);
+ a.SetHopcount (2);
+ a.SetTTL (4);
+ a.DecrementTtl ();
+ NS_TEST_ASSERT_EQUAL (a.GetTtl(), 3);
+ a.SetOriginatorAddress (Mac48Address ("11:22:33:44:55:66"));
+ a.SetDestSeqNumber (5);
+ a.SetMetric (6);
+ a.IncrementMetric (2);
+ NS_TEST_ASSERT_EQUAL (a.GetMetric(), 8);
+
+ // test roundtrip serialization
+ Ptr<Packet> packet = Create<Packet> ();
+ packet->AddHeader (a);
+ IeRann b;
+ packet->RemoveHeader (b);
+ NS_TEST_ASSERT_EQUAL (a, b);
+
+ // test FindFirst()
+ packet->AddHeader (a);
+ IeRann c;
+ bool ok = c.FindFirst(packet);
+ NS_TEST_ASSERT (ok);
+ NS_TEST_ASSERT_EQUAL (a, c);
+
+ return result;
+}
+#endif // RUN_SELF_TESTS
+
+}} // namespace ns3::dot11s
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-rann.h Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#ifndef RANN_INFORMATION_ELEMENT_H
+#define RANN_INFORMATION_ELEMENT_H
+
+#include "ns3/mac48-address.h"
+#include "ns3/wifi-information-element.h"
+
+namespace ns3 {
+namespace dot11s {
+/**
+ * \ingroup dot11s
+ * \brief See 7.3.2.95 of 802.11s draft 2.07
+ */
+class IeRann : public WifiInformationElement
+{
+public:
+ IeRann ();
+ virtual ~IeRann ();
+ static TypeId GetTypeId ();
+ virtual TypeId GetInstanceTypeId () const;
+ void SetFlags (uint8_t flags);
+ void SetHopcount (uint8_t hopcount);
+ void SetTTL (uint8_t ttl);
+ void SetOriginatorAddress (Mac48Address originator_address);
+ void SetDestSeqNumber (uint32_t dest_seq_number);
+ void SetMetric (uint32_t metric);
+ uint8_t GetFlags ();
+ uint8_t GetHopcount ();
+ uint8_t GetTtl ();
+ Mac48Address GetOriginatorAddress ();
+ uint32_t GetDestSeqNumber ();
+ uint32_t GetMetric ();
+ void DecrementTtl ();
+ void IncrementMetric (uint32_t metric);
+
+private:
+ WifiElementId ElementId () const{
+ return IE11S_RANN;
+ }
+ void SerializeInformation (Buffer::Iterator i) const;
+ uint8_t DeserializeInformation (Buffer::Iterator start, uint8_t length);
+ uint8_t GetInformationSize () const;
+ void PrintInformation (std::ostream &os) const;
+
+ uint8_t m_flags;
+ uint8_t m_hopcount;
+ uint8_t m_ttl;
+ Mac48Address m_originatorAddress;
+ uint32_t m_destSeqNumber;
+ uint32_t m_metric;
+
+ friend bool operator== (const IeRann & a, const IeRann & b);
+};
+
+bool operator== (const IeRann & a, const IeRann & b);
+
+} // namespace dot11s
+} //namespace ns3
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/peer-link-frame.cc Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,230 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#include "peer-link-frame.h"
+#include "ns3/mesh-wifi-interface-mac.h"
+#include "ns3/test.h"
+#include "ns3/packet.h"
+namespace ns3 {
+namespace dot11s {
+NS_OBJECT_ENSURE_REGISTERED (PeerLinkFrameStart);
+
+PeerLinkFrameStart::PeerLinkFrameStart ():
+ m_subtype (255),
+ m_aid (0),
+ m_rates (SupportedRates()),
+ m_meshId (Ssid())
+{
+}
+void
+PeerLinkFrameStart::SetPlinkFrameSubtype(uint8_t subtype)
+{
+ m_subtype = subtype;
+}
+void
+PeerLinkFrameStart::SetPlinkFrameStart(PeerLinkFrameStart::PlinkFrameStartFields fields)
+{
+ m_subtype = fields.subtype;
+ if(m_subtype == (uint8_t)(WifiMeshMultihopActionHeader::PEER_LINK_CONFIRM))
+ m_aid = fields.aid;
+ if(m_subtype != (uint8_t)(WifiMeshMultihopActionHeader::PEER_LINK_CLOSE))
+ {
+ m_rates = fields.rates;
+ m_meshId = fields.meshId;
+ }
+ else
+ m_reasonCode = fields.reasonCode;
+}
+
+PeerLinkFrameStart::PlinkFrameStartFields
+PeerLinkFrameStart::GetFields ()
+{
+ PlinkFrameStartFields retval;
+ retval.subtype = m_subtype;
+ retval.aid = m_aid;
+ retval.rates = m_rates;
+ retval.meshId = m_meshId;
+ return retval;
+}
+
+bool
+PeerLinkFrameStart::CheckPlinkFrameStart(Ptr<MeshWifiInterfaceMac> mac)
+{
+ bool retval;
+ retval = mac->CheckSupportedRates(m_rates);
+ if(! retval)
+ return retval;
+ retval = mac->CheckMeshId(m_meshId);
+ return true;
+}
+
+TypeId
+PeerLinkFrameStart::GetTypeId ()
+{
+ static TypeId tid =
+ TypeId ("ns3::dot11s::PeerLinkFrameStart")
+ .SetParent<Header> ()
+ .AddConstructor<PeerLinkFrameStart> ()
+ ;
+ return tid;
+}
+
+TypeId
+PeerLinkFrameStart::GetInstanceTypeId () const
+{
+ return GetTypeId ();
+}
+void
+PeerLinkFrameStart::Print (std::ostream &os) const
+{
+ os << "subtype = " << (uint16_t)m_subtype
+ << "\naid = " << (uint16_t)m_aid
+ << "\nrates = " << m_rates
+ << "\nmeshId = " << m_meshId;
+}
+
+uint32_t
+PeerLinkFrameStart::GetSerializedSize () const
+{
+ uint32_t size = 0;
+ NS_ASSERT(m_subtype < 3);
+ if ((uint8_t)(WifiMeshMultihopActionHeader::PEER_LINK_CONFIRM) == m_subtype)
+ size += 2; //AID of remote peer
+ if ((uint8_t)(WifiMeshMultihopActionHeader::PEER_LINK_CLOSE) != m_subtype)
+ {
+ size += m_rates.GetSerializedSize ();
+ size += 2;
+ size += m_meshId.GetSerializedSize ();
+ }
+ else
+ size += 2; //reasonCode
+ return size;
+}
+
+void
+PeerLinkFrameStart::Serialize (Buffer::Iterator start) const
+{
+ Buffer::Iterator i = start;
+ NS_ASSERT(m_subtype < 3);
+ //i.WriteU8 (m_subtype);
+ if ((uint8_t)(WifiMeshMultihopActionHeader::PEER_LINK_CONFIRM) == m_subtype)
+ i.WriteHtonU16 (m_aid);
+ if ((uint8_t)(WifiMeshMultihopActionHeader::PEER_LINK_CLOSE) != m_subtype)
+ {
+ i = m_rates.Serialize (i);
+ i.Next(2); //QoS
+ i = m_meshId.Serialize (i);
+ }
+ else
+ i.WriteHtonU16(m_reasonCode);
+}
+
+uint32_t
+PeerLinkFrameStart::Deserialize (Buffer::Iterator start)
+{
+ Buffer::Iterator i = start;
+ NS_ASSERT(m_subtype < 3);
+ //m_subtype = (IePeerManagement::Subtype)i.ReadU8 ();
+ if ((uint8_t)(WifiMeshMultihopActionHeader::PEER_LINK_CONFIRM) == m_subtype)
+ m_aid = i.ReadNtohU16 ();
+ if ((uint8_t)(WifiMeshMultihopActionHeader::PEER_LINK_CLOSE) != m_subtype)
+ {
+ i = m_rates.Deserialize (i);
+ i.Next(2); //QoS
+ i = m_meshId.Deserialize (i);
+ }
+ else
+ m_reasonCode = i.ReadNtohU16();
+ return i.GetDistanceFrom (start);
+}
+bool operator== (const PeerLinkFrameStart & a, const PeerLinkFrameStart & b)
+{
+ return (
+ (a.m_subtype == b.m_subtype) &&
+ (a.m_aid == b.m_aid) &&
+ (a.m_meshId.IsEqual(b.m_meshId))
+ );
+}
+#ifdef RUN_SELF_TESTS
+
+/// Built-in self test for PeerLinkFrameStart
+struct PeerLinkFrameStartBist : public Test
+{
+ PeerLinkFrameStartBist () : Test ("Mesh/802.11s/IE/PeerLinkFrameStart") {}
+ virtual bool RunTests();
+};
+
+/// Test instance
+static PeerLinkFrameStartBist g_PeerLinkFrameStartBist;
+
+bool PeerLinkFrameStartBist::RunTests ()
+{
+ bool result (true);
+ {
+ PeerLinkFrameStart a;
+ PeerLinkFrameStart::PlinkFrameStartFields fields;
+ fields.subtype = (uint8_t)(WifiMeshMultihopActionHeader::PEER_LINK_OPEN);
+ fields.aid = 101;
+ fields.reasonCode = 12;
+ fields.meshId = Ssid("qwertyuiop");
+ a.SetPlinkFrameStart(fields);
+ Ptr<Packet> packet = Create<Packet> ();
+ packet->AddHeader (a);
+ PeerLinkFrameStart b;
+ b.SetPlinkFrameSubtype((uint8_t)(WifiMeshMultihopActionHeader::PEER_LINK_OPEN));
+ packet->RemoveHeader (b);
+ NS_TEST_ASSERT_EQUAL (a, b);
+ }
+ {
+ PeerLinkFrameStart a;
+ PeerLinkFrameStart::PlinkFrameStartFields fields;
+ fields.subtype = (uint8_t)(WifiMeshMultihopActionHeader::PEER_LINK_CONFIRM);
+ fields.aid = 1234;
+ fields.reasonCode = 12;
+ fields.meshId = Ssid("qwerty");
+ a.SetPlinkFrameStart(fields);
+ Ptr<Packet> packet = Create<Packet> ();
+ packet->AddHeader (a);
+ PeerLinkFrameStart b;
+ b.SetPlinkFrameSubtype((uint8_t)(WifiMeshMultihopActionHeader::PEER_LINK_CONFIRM));
+ packet->RemoveHeader (b);
+ NS_TEST_ASSERT_EQUAL (a, b);
+ }
+ {
+ PeerLinkFrameStart a;
+ PeerLinkFrameStart::PlinkFrameStartFields fields;
+ fields.subtype = (uint8_t)(WifiMeshMultihopActionHeader::PEER_LINK_CLOSE);
+ fields.aid = 10;
+ fields.meshId = Ssid("qqq");
+ fields.reasonCode = 12;
+ a.SetPlinkFrameStart(fields);
+ Ptr<Packet> packet = Create<Packet> ();
+ packet->AddHeader (a);
+ PeerLinkFrameStart b;
+ b.SetPlinkFrameSubtype((uint8_t)(WifiMeshMultihopActionHeader::PEER_LINK_CLOSE));
+ packet->RemoveHeader (b);
+ NS_TEST_ASSERT_EQUAL (a, b);
+ }
+ return result;
+}
+#endif
+} // namespace dot11s
+} //namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/peer-link-frame.h Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,84 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#ifndef PEER_LINK_FRAME_START_H
+#define PEER_LINK_FRAME_START_H
+#include "ns3/header.h"
+#include "ns3/supported-rates.h"
+#include "ns3/ssid.h"
+#include "dot11s-mac-header.h"
+namespace ns3 {
+class MeshWifiInterfaceMac;
+namespace dot11s {
+/**
+ * \ingroup dot11s
+ *
+ * \brief 802.11s Peer link management frame:
+ * \details included the following (see chapters 7.4.12.1-7.4.12.3 of
+ * 802.11s):
+ * - Subtype field
+ * - Association ID field
+ * - Supported rates
+ * - SSID of mesh
+ */
+class PeerLinkFrameStart : public Header
+{
+public:
+ PeerLinkFrameStart ();
+ ///\brief fields:
+ struct PlinkFrameStartFields
+ {
+ uint8_t subtype;
+ uint16_t reasonCode; //close only
+ uint16_t aid; //confirm only
+ SupportedRates rates; //open and confirm
+ Ssid meshId; //open and confirm
+ };
+ ///\attention: must be set before deserialize, before only multihop
+ //action header knows about subtype
+ void SetPlinkFrameSubtype(uint8_t subtype);
+ void SetPlinkFrameStart(PlinkFrameStartFields);
+ PlinkFrameStartFields GetFields ();
+ bool CheckPlinkFrameStart(Ptr<MeshWifiInterfaceMac> mac);
+ /** \name Inherited from header:
+ * \{
+ */
+ static TypeId GetTypeId ();
+ virtual TypeId GetInstanceTypeId () const;
+ virtual void Print (std::ostream &os) const;
+ virtual uint32_t GetSerializedSize () const;
+ virtual void Serialize (Buffer::Iterator start) const;
+ virtual uint32_t Deserialize (Buffer::Iterator start);
+ /**
+ * \}
+ */
+private:
+ uint8_t m_subtype;
+ uint16_t m_reasonCode;
+ uint16_t m_aid;
+ SupportedRates m_rates;
+ Ssid m_meshId;
+
+ friend bool operator== (const PeerLinkFrameStart & a, const PeerLinkFrameStart & b);
+};
+bool operator== (const PeerLinkFrameStart & a, const PeerLinkFrameStart & b);
+} //namespace dot11s
+} //namespace ns3
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/peer-link.cc Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,568 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ * Aleksey Kovalenko <kovalenko@iitp.ru>
+ * Pavel Boyko <boyko@iitp.ru>
+ */
+
+#include "peer-link.h"
+#include "ns3/log.h"
+#include "ns3/simulator.h"
+#include "ns3/traced-value.h"
+
+NS_LOG_COMPONENT_DEFINE ("Dot11sPeerManagementProtocol");
+
+namespace ns3 {
+namespace dot11s {
+
+NS_OBJECT_ENSURE_REGISTERED(PeerLink);
+
+TypeId
+PeerLink::GetTypeId()
+{
+ static TypeId tid = TypeId ("ns3::dot11s::PeerLink")
+ .SetParent<Object> ()
+ .AddConstructor<PeerLink> ()
+ .AddAttribute ("RetryTimeout", "Retry timeout",
+ TimeValue (TimeValue (MicroSeconds (40 * 1024))),
+ MakeTimeAccessor (&PeerLink::m_dot11MeshRetryTimeout),
+ MakeTimeChecker ()
+ )
+ .AddAttribute ("HoldingTimeout", "Holding timeout",
+ TimeValue (TimeValue (MicroSeconds (40 * 1024))),
+ MakeTimeAccessor (&PeerLink::m_dot11MeshHoldingTimeout),
+ MakeTimeChecker ()
+ )
+ .AddAttribute ("ConfirmTimeout", "Confirm timeout",
+ TimeValue (TimeValue (MicroSeconds (40 * 1024))),
+ MakeTimeAccessor (&PeerLink::m_dot11MeshConfirmTimeout),
+ MakeTimeChecker ()
+ )
+ .AddAttribute ("MaxRetries", "Maximum number of retries",
+ UintegerValue (4),
+ MakeUintegerAccessor (&PeerLink::m_dot11MeshMaxRetries),
+ MakeUintegerChecker<uint16_t> ()
+ )
+ .AddAttribute ("MaxBeaconLoss", "Maximum number of lost beacons before link will be closed",
+ UintegerValue (2),
+ MakeUintegerAccessor (&PeerLink::m_maxBeaconLoss),
+ MakeUintegerChecker<uint16_t> (1)
+ );
+ return tid;
+}
+
+//-----------------------------------------------------------------------------
+// PeerLink public interface
+//-----------------------------------------------------------------------------
+PeerLink::PeerLink ():
+ m_peerAddress (Mac48Address::GetBroadcast ()),
+ m_peerMeshPointAddress (Mac48Address::GetBroadcast ()),
+ m_localLinkId (0),
+ m_peerLinkId (0),
+ m_state (IDLE),
+ m_retryCounter (0)
+{
+}
+void
+PeerLink::SetPeerAddress (Mac48Address macaddr)
+{
+ m_peerAddress = macaddr;
+}
+void
+PeerLink::SetPeerMeshPointAddress(Mac48Address macaddr)
+{
+ m_peerMeshPointAddress = macaddr;
+}
+void
+PeerLink::SetInterface (uint32_t interface)
+{
+ m_interface = interface;
+}
+void
+PeerLink::SetLocalLinkId (uint16_t id)
+{
+ m_localLinkId = id;
+}
+void
+PeerLink::SetLocalAid (uint16_t aid)
+{
+ m_assocId = aid;
+}
+void
+PeerLink::SetBeaconInformation (Time lastBeacon, Time beaconInterval)
+{
+ m_lastBeacon = lastBeacon;
+ m_beaconInterval = beaconInterval;
+ m_beaconLossTimer.Cancel ();
+ Time delay = Seconds(beaconInterval.GetSeconds() * m_maxBeaconLoss);
+ NS_ASSERT (delay.GetMicroSeconds() != 0);
+ m_beaconLossTimer = Simulator::Schedule (delay, &PeerLink::BeaconLoss, this);
+}
+void
+PeerLink::MLMESetSignalStatusCallback (PeerLink::SignalStatusCallback cb)
+{
+ m_linkStatusCallback = cb;
+}
+void
+PeerLink::BeaconLoss ()
+{
+ StateMachine (CNCL);
+}
+void
+PeerLink::SetBeaconTimingElement (IeBeaconTiming beaconTiming)
+{
+ m_beaconTiming = beaconTiming;
+}
+Mac48Address
+PeerLink::GetPeerAddress () const
+{
+ return m_peerAddress;
+}
+uint16_t
+PeerLink::GetLocalAid () const
+{
+ return m_assocId;
+}
+Time
+PeerLink::GetLastBeacon () const
+{
+ return m_lastBeacon;
+}
+Time
+PeerLink::GetBeaconInterval () const
+{
+ return m_beaconInterval;
+}
+IeBeaconTiming
+PeerLink::GetBeaconTimingElement () const
+{
+ return m_beaconTiming;
+}
+void
+PeerLink::ClearTimingElement ()
+{
+ m_beaconTiming.ClearTimingElement ();
+}
+void
+PeerLink::MLMECancelPeerLink (PmpReasonCode reason)
+{
+ StateMachine (CNCL,reason);
+}
+void
+PeerLink::MLMEPassivePeerLinkOpen ()
+{
+ StateMachine (PASOPN);
+}
+void
+PeerLink::MLMEActivePeerLinkOpen ()
+{
+ StateMachine (ACTOPN);
+}
+void
+PeerLink::MLMEPeeringRequestReject ()
+{
+ StateMachine (REQ_RJCT, REASON11S_PEER_LINK_CANCELLED);
+}
+void
+PeerLink::Close (uint16_t localLinkId, uint16_t peerLinkId, PmpReasonCode reason)
+{
+ if (peerLinkId != 0 && m_localLinkId != peerLinkId)
+ return;
+ if (m_peerLinkId == 0)
+ m_peerLinkId = localLinkId;
+ else if (m_peerLinkId != localLinkId)
+ return;
+ StateMachine (CLS_ACPT, reason);
+}
+void
+PeerLink::OpenAccept (uint16_t localLinkId, IeConfiguration conf, Mac48Address peerMp)
+{
+ if (m_peerLinkId == 0)
+ m_peerLinkId = localLinkId;
+ m_configuration = conf;
+ if(m_peerMeshPointAddress != Mac48Address::GetBroadcast ())
+ {
+ NS_ASSERT(m_peerMeshPointAddress == peerMp);
+ }
+ else
+ m_peerMeshPointAddress = peerMp;
+ StateMachine (OPN_ACPT);
+}
+void
+PeerLink::OpenReject (uint16_t localLinkId, IeConfiguration conf, Mac48Address peerMp, PmpReasonCode reason)
+{
+ if ( m_peerLinkId == 0)
+ m_peerLinkId = localLinkId;
+ m_configuration = conf;
+ if(m_peerMeshPointAddress != Mac48Address::GetBroadcast ())
+ {
+ NS_ASSERT(m_peerMeshPointAddress == peerMp);
+ }
+ else
+ m_peerMeshPointAddress = peerMp;
+ StateMachine (OPN_RJCT, reason);
+}
+void
+PeerLink::ConfirmAccept (uint16_t localLinkId, uint16_t peerLinkId, uint16_t peerAid, IeConfiguration conf, Mac48Address peerMp)
+{
+ if ( m_localLinkId != peerLinkId)
+ return;
+ if ( m_peerLinkId == 0)
+ m_peerLinkId = localLinkId;
+ else if ( m_peerLinkId != localLinkId )
+ return;
+ m_configuration = conf;
+ m_peerAssocId = peerAid;
+ if(m_peerMeshPointAddress != Mac48Address::GetBroadcast ())
+ {
+ NS_ASSERT(m_peerMeshPointAddress == peerMp);
+ }
+ else
+ m_peerMeshPointAddress = peerMp;
+ StateMachine (CNF_ACPT);
+}
+void
+PeerLink::ConfirmReject (uint16_t localLinkId, uint16_t peerLinkId,
+ IeConfiguration conf, Mac48Address peerMp, PmpReasonCode reason)
+{
+ if (m_localLinkId != peerLinkId)
+ return;
+ if (m_peerLinkId == 0)
+ m_peerLinkId = localLinkId;
+ else if (m_peerLinkId != localLinkId)
+ return;
+ m_configuration = conf;
+ if(m_peerMeshPointAddress != Mac48Address::GetBroadcast ())
+ {
+ NS_ASSERT(m_peerMeshPointAddress == peerMp);
+ }
+ m_peerMeshPointAddress = peerMp;
+ StateMachine (CNF_RJCT, reason);
+}
+bool
+PeerLink::LinkIsEstab () const
+{
+ return (m_state == ESTAB);
+}
+bool
+PeerLink::LinkIsIdle () const
+{
+ return (m_state == IDLE);
+}
+void
+PeerLink::SetMacPlugin(Ptr<PeerManagerMacPlugin> plugin)
+{
+ m_macPlugin = plugin;
+}
+//-----------------------------------------------------------------------------
+// Private
+//-----------------------------------------------------------------------------
+void
+PeerLink::StateMachine (PeerEvent event,PmpReasonCode reasoncode)
+{
+ switch (m_state)
+ {
+ case IDLE:
+ switch (event)
+ {
+ case CNCL:
+ case CLS_ACPT:
+ m_state = IDLE;
+ // TODO Callback MLME-SignalPeerLinkStatus
+ break;
+ case REQ_RJCT:
+ SendPeerLinkClose (reasoncode);
+ break;
+ case ACTOPN:
+ m_state = OPN_SNT;
+ SendPeerLinkOpen ();
+ SetRetryTimer ();
+ break;
+ case OPN_ACPT:
+ m_state = OPN_RCVD;
+ SendPeerLinkConfirm ();
+ SendPeerLinkOpen ();
+ SetRetryTimer ();
+ break;
+ default:
+ {}
+ }
+ break;
+ case OPN_SNT:
+ switch (event)
+ {
+ case TOR1:
+ SendPeerLinkOpen ();
+ m_retryCounter++;
+ SetRetryTimer ();
+ break;
+ case CNF_ACPT:
+ m_state = CNF_RCVD;
+ ClearRetryTimer ();
+ SetConfirmTimer ();
+ break;
+ case OPN_ACPT:
+ m_state = OPN_RCVD;
+ SendPeerLinkConfirm ();
+ break;
+ case CLS_ACPT:
+ m_state = HOLDING;
+ ClearRetryTimer ();
+ SendPeerLinkClose (REASON11S_MESH_CLOSE_RCVD);
+ SetHoldingTimer ();
+ break;
+ case OPN_RJCT:
+ case CNF_RJCT:
+ m_state = HOLDING;
+ ClearRetryTimer ();
+ SendPeerLinkClose (reasoncode);
+ SetHoldingTimer ();
+ break;
+ case TOR2:
+ m_state = HOLDING;
+ ClearRetryTimer ();
+ SendPeerLinkClose (REASON11S_MESH_MAX_RETRIES);
+ SetHoldingTimer ();
+ break;
+ case CNCL:
+ m_state = HOLDING;
+ ClearRetryTimer ();
+ SendPeerLinkClose (REASON11S_PEER_LINK_CANCELLED);
+ SetHoldingTimer ();
+ break;
+ default:
+ {}
+ }
+ break;
+ case CNF_RCVD:
+ switch (event)
+ {
+ case CNF_ACPT:
+ break;
+ case OPN_ACPT:
+ m_state = ESTAB;
+ ClearConfirmTimer ();
+ SendPeerLinkConfirm ();
+ NS_ASSERT(m_peerMeshPointAddress != Mac48Address::GetBroadcast ());
+ m_linkStatusCallback (m_interface, m_peerAddress, m_peerMeshPointAddress, true);
+ // TODO Callback MLME-SignalPeerLinkStatus
+ break;
+ case CLS_ACPT:
+ m_state = HOLDING;
+ ClearConfirmTimer ();
+ SendPeerLinkClose (REASON11S_MESH_CLOSE_RCVD);
+ SetHoldingTimer ();
+ break;
+ case CNF_RJCT:
+ case OPN_RJCT:
+ m_state = HOLDING;
+ ClearConfirmTimer ();
+ SendPeerLinkClose (reasoncode);
+ SetHoldingTimer ();
+ break;
+ case CNCL:
+ m_state = HOLDING;
+ ClearConfirmTimer ();
+ SendPeerLinkClose (REASON11S_PEER_LINK_CANCELLED);
+ SetHoldingTimer ();
+ break;
+ case TOC:
+ m_state = HOLDING;
+ SendPeerLinkClose (REASON11S_MESH_CONFIRM_TIMEOUT);
+ SetHoldingTimer ();
+ break;
+ default:
+ {}
+ }
+ break;
+ case OPN_RCVD:
+ switch (event)
+ {
+ case TOR1:
+ SendPeerLinkOpen ();
+ m_retryCounter++;
+ SetRetryTimer ();
+ break;
+ case CNF_ACPT:
+ m_state = ESTAB;
+ ClearRetryTimer ();
+ NS_ASSERT(m_peerMeshPointAddress != Mac48Address::GetBroadcast ());
+ m_linkStatusCallback (m_interface, m_peerAddress, m_peerMeshPointAddress, true);
+ // TODO Callback MLME-SignalPeerLinkStatus
+ break;
+ case CLS_ACPT:
+ m_state = HOLDING;
+ ClearRetryTimer ();
+ SendPeerLinkClose (REASON11S_MESH_CLOSE_RCVD);
+ SetHoldingTimer ();
+ break;
+ case OPN_RJCT:
+ case CNF_RJCT:
+ m_state = HOLDING;
+ ClearRetryTimer ();
+ SendPeerLinkClose (reasoncode);
+ SetHoldingTimer ();
+ break;
+ case TOR2:
+ m_state = HOLDING;
+ ClearRetryTimer ();
+ SendPeerLinkClose (REASON11S_MESH_MAX_RETRIES);
+ SetHoldingTimer ();
+ break;
+ case CNCL:
+ m_state = HOLDING;
+ ClearRetryTimer ();
+ SendPeerLinkClose (REASON11S_PEER_LINK_CANCELLED);
+ SetHoldingTimer ();
+ break;
+ default:
+ {}
+ }
+ break;
+ case ESTAB:
+ switch (event)
+ {
+ case OPN_ACPT:
+ SendPeerLinkConfirm ();
+ break;
+ case CLS_ACPT:
+ m_state = HOLDING;
+ SendPeerLinkClose (REASON11S_MESH_CLOSE_RCVD);
+ SetHoldingTimer ();
+ m_linkStatusCallback (m_interface, m_peerAddress, m_peerMeshPointAddress, false);
+ break;
+ case OPN_RJCT:
+ case CNF_RJCT:
+ m_state = HOLDING;
+ ClearRetryTimer ();
+ SendPeerLinkClose (reasoncode);
+ SetHoldingTimer ();
+ m_linkStatusCallback (m_interface, m_peerAddress, m_peerMeshPointAddress, false);
+ break;
+ case CNCL:
+ m_state = HOLDING;
+ SendPeerLinkClose (REASON11S_PEER_LINK_CANCELLED);
+ SetHoldingTimer ();
+ m_linkStatusCallback (m_interface, m_peerAddress, m_peerMeshPointAddress, false);
+ break;
+ default:
+ {}
+ }
+ break;
+ case HOLDING:
+ switch (event)
+ {
+ case CLS_ACPT:
+ ClearHoldingTimer ();
+ case TOH:
+ m_state = IDLE;
+ // TODO Callback MLME-SignalPeerLinkStatus
+ break;
+ case OPN_ACPT:
+ case CNF_ACPT:
+ m_state = HOLDING;
+ // reason not spec in D2.0
+ SendPeerLinkClose (REASON11S_PEER_LINK_CANCELLED);
+ break;
+ case OPN_RJCT:
+ case CNF_RJCT:
+ m_state = HOLDING;
+ SendPeerLinkClose (reasoncode);
+ break;
+ default:
+ {}
+ }
+ break;
+ }
+}
+void
+PeerLink::ClearRetryTimer ()
+{
+ m_retryTimer.Cancel ();
+}
+void
+PeerLink::ClearConfirmTimer ()
+{
+ m_confirmTimer.Cancel ();
+}
+void
+PeerLink::ClearHoldingTimer ()
+{
+ m_holdingTimer.Cancel ();
+}
+void
+PeerLink::SendPeerLinkClose (PmpReasonCode reasoncode)
+{
+ IePeerManagement peerElement;
+ peerElement.SetPeerClose (m_localLinkId, m_peerLinkId, reasoncode);
+ m_macPlugin->SendPeerLinkManagementFrame (m_peerAddress, m_peerMeshPointAddress, m_assocId, peerElement, m_configuration);
+}
+void
+PeerLink::SendPeerLinkOpen ()
+{
+ IePeerManagement peerElement;
+ peerElement.SetPeerOpen (m_localLinkId);
+ NS_ASSERT (m_macPlugin != NULL);
+ m_macPlugin->SendPeerLinkManagementFrame (m_peerAddress, m_peerMeshPointAddress, m_assocId, peerElement, m_configuration);
+}
+void
+PeerLink::SendPeerLinkConfirm ()
+{
+ IePeerManagement peerElement;
+ peerElement.SetPeerConfirm (m_localLinkId, m_peerLinkId);
+ m_macPlugin->SendPeerLinkManagementFrame (m_peerAddress, m_peerMeshPointAddress, m_assocId, peerElement, m_configuration);
+}
+void
+PeerLink::SetHoldingTimer ()
+{
+ NS_ASSERT(m_dot11MeshHoldingTimeout.GetMicroSeconds() !=0);
+ m_holdingTimer = Simulator::Schedule (m_dot11MeshHoldingTimeout, &PeerLink::HoldingTimeout, this);
+}
+void
+PeerLink::HoldingTimeout ()
+{
+ StateMachine (TOH);
+}
+void
+PeerLink::SetRetryTimer ()
+{
+ NS_ASSERT(m_dot11MeshRetryTimeout.GetMicroSeconds() !=0);
+ m_retryTimer = Simulator::Schedule (m_dot11MeshRetryTimeout, &PeerLink::RetryTimeout, this);
+}
+void
+PeerLink::RetryTimeout ()
+{
+ if ( m_retryCounter < m_dot11MeshMaxRetries)
+ StateMachine (TOR1);
+ else
+ StateMachine (TOR2);
+}
+void
+PeerLink::SetConfirmTimer ()
+{
+ NS_ASSERT(m_dot11MeshConfirmTimeout.GetMicroSeconds() !=0);
+ m_confirmTimer = Simulator::Schedule (m_dot11MeshConfirmTimeout, &PeerLink::ConfirmTimeout, this);
+}
+void
+PeerLink::ConfirmTimeout ()
+{
+ StateMachine (TOC);
+}
+} // namespace dot11s
+} //namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/peer-link.h Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,261 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ * Aleksey Kovalenko <kovalenko@iitp.ru>
+ */
+
+#ifndef PEERLLINK_H_
+#define PEERLLINK_H_
+
+#include "ns3/nstime.h"
+#include "ns3/callback.h"
+#include "ns3/mac48-address.h"
+#include "ns3/event-id.h"
+#include "ie-dot11s-beacon-timing.h"
+#include "ie-dot11s-peer-management.h"
+#include "ie-dot11s-configuration.h"
+#include "peer-management-plugin.h"
+namespace ns3 {
+namespace dot11s {
+/**
+ * \ingroup dot11s
+ *
+ * \brief Peer link model for 802.11s Peer Management protocol
+ */
+class PeerLink : public Object
+{
+public:
+ friend class PeerManagementProtocol;
+ /// Support object system
+ static TypeId GetTypeId();
+ /// C-tor create empty link
+ PeerLink ();
+
+ /// Process beacon received from peer
+ void SetBeaconInformation (Time lastBeacon, Time BeaconInterval);
+ /**
+ * \brief Method used to detecet peer link changes
+ *
+ * \param bool if true - opened new link, if false - link closed
+ */
+ void SetLinkStatusCallback (Callback<void, uint32_t, Mac48Address, bool> cb);
+ /**
+ * \name Peer link geeters/setters
+ * \{
+ */
+ void SetPeerAddress (Mac48Address macaddr);
+ void SetPeerMeshPointAddress (Mac48Address macaddr);
+ void SetInterface (uint32_t interface);
+ void SetLocalLinkId (uint16_t id);
+ void SetPeerLinkId (uint16_t id);
+ void SetLocalAid (uint16_t aid);
+ void SetPeerAid (uint16_t aid);
+ void SetBeaconTimingElement (IeBeaconTiming beaconTiming);
+ void SetPeerLinkDescriptorElement (IePeerManagement peerLinkElement);
+ Mac48Address GetPeerAddress () const;
+ uint16_t GetLocalAid () const;
+ Time GetLastBeacon () const;
+ Time GetBeaconInterval () const;
+ IeBeaconTiming GetBeaconTimingElement ()const;
+ IePeerManagement GetPeerLinkDescriptorElement ()const;
+ void ClearTimingElement ();
+ //\}
+
+ /**
+ * \name MLME
+ * \{
+ */
+ /// MLME-CancelPeerLink.request
+ void MLMECancelPeerLink (PmpReasonCode reason);
+ /// MLME-PassivePeerLinkOpen.request
+ void MLMEPassivePeerLinkOpen ();
+ /// MLME-ActivePeerLinkOpen.request
+ void MLMEActivePeerLinkOpen ();
+ /// MLME-PeeringRequestReject
+ void MLMEPeeringRequestReject ();
+ /// Callback type for MLME-SignalPeerLinkStatus event
+ typedef Callback<void, uint32_t, Mac48Address, Mac48Address, bool> SignalStatusCallback;
+ /// Set callback
+ void MLMESetSignalStatusCallback (SignalStatusCallback);
+ //\}
+private:
+ /**
+ * \name Link response to received management frames
+ *
+ * \attention In all this methods {local/peer}LinkID correspond to _peer_ station, as written in
+ * received frame, e.g. I am peerLinkID and peer link is localLinkID .
+ *
+ * TODO is that clear?
+ *
+ * \{
+ */
+ /// Close link
+ void Close (uint16_t localLinkID, uint16_t peerLinkID, PmpReasonCode reason);
+ /// Accept open link
+ void OpenAccept (uint16_t localLinkId, IeConfiguration conf, Mac48Address peerMp);
+ /// Reject open link
+ void OpenReject (uint16_t localLinkId, IeConfiguration conf, Mac48Address peerMp, PmpReasonCode reason);
+ /// Confirm accept
+ void ConfirmAccept (
+ uint16_t localLinkId,
+ uint16_t peerLinkId,
+ uint16_t peerAid,
+ IeConfiguration conf,
+ Mac48Address peerMp
+ );
+ /// Confirm reject
+ void ConfirmReject (
+ uint16_t localLinkId,
+ uint16_t peerLinkId,
+ IeConfiguration conf,
+ Mac48Address peerMp,
+ PmpReasonCode reason
+ );
+ //\}
+
+ /// True if link is established
+ bool LinkIsEstab () const;
+ /// True if link is idle. Link can be deleted in this state
+ bool LinkIsIdle () const;
+ /**
+ * Set pointer to MAC-plugin, which is responsible for sending peer
+ * link management frames
+ */
+ void SetMacPlugin(Ptr<PeerManagerMacPlugin> plugin);
+private:
+ /// Peer link states, see 802.11s draft 11B.3.3.1
+ enum PeerState {
+ IDLE,
+ OPN_SNT,
+ CNF_RCVD,
+ OPN_RCVD,
+ ESTAB,
+ HOLDING,
+ };
+ /// Peer link events, see 802.11s draft 11B.3.3.2
+ enum PeerEvent
+ {
+ CNCL, ///< MLME-CancelPeerLink
+ PASOPN, ///< MLME-PassivePeerLinkOpen
+ ACTOPN, ///< MLME-ActivePeerLinkOpen
+ CLS_ACPT, ///< PeerLinkClose_Accept
+ OPN_ACPT, ///< PeerLinkOpen_Accept
+ OPN_RJCT, ///< PeerLinkOpen_Reject
+ REQ_RJCT, ///< PeerLinkOpenReject by internal reason
+ CNF_ACPT, ///< PeerLinkConfirm_Accept
+ CNF_RJCT, ///< PeerLinkConfirm_Reject
+ TOR1, ///< Timeout of retry timer
+ TOR2, ///< also timeout of retry timer
+ TOC, ///< Timeout of confirm timer
+ TOH, ///< Timeout of holding (gracefull closing) timer
+ };
+
+private:
+ /// State transition
+ void StateMachine (PeerEvent event, PmpReasonCode = REASON11S_RESERVED);
+
+ /**
+ * \name Event handlers
+ * \{
+ */
+ void ClearRetryTimer ();
+ void ClearConfirmTimer ();
+ void ClearHoldingTimer ();
+ void SetHoldingTimer ();
+ void SetRetryTimer ();
+ void SetConfirmTimer ();
+ //\}
+
+ /**
+ * \name Work with management frames
+ * \{
+ */
+ void SendPeerLinkClose (PmpReasonCode reasoncode);
+ void SendPeerLinkOpen ();
+ void SendPeerLinkConfirm ();
+ //\}
+
+ /**
+ * \name Timeout handlers
+ * \{
+ */
+ void HoldingTimeout ();
+ void RetryTimeout ();
+ void ConfirmTimeout ();
+ //\}
+
+private:
+ ///The number of interface I am associated with
+ uint32_t m_interface;
+ /// pointer to mac plugin, which is responsible for peer management
+ Ptr<PeerManagerMacPlugin> m_macPlugin;
+ /// Peer address
+ Mac48Address m_peerAddress;
+ /// Mesh point address, equal to peer address in case of single
+ //interface mesh point
+ Mac48Address m_peerMeshPointAddress;
+ /// My ID of this link
+ uint16_t m_localLinkId;
+ /// Peer ID of this link
+ uint16_t m_peerLinkId;
+ /// My association ID
+ uint16_t m_assocId;
+ /// Assoc Id assigned to me by peer
+ uint16_t m_peerAssocId;
+
+ /// When last beacon was sent (TODO or received?)
+ Time m_lastBeacon;
+ /// Current beacon interval on corresponding interface
+ Time m_beaconInterval;
+
+ /// Current state
+ PeerState m_state;
+ /// Mesh interface configuration
+ IeConfiguration m_configuration;
+
+ // State is a bitfield as defined as follows:
+ // This are states for a given
+ IeBeaconTiming m_beaconTiming;
+
+ /**
+ * \name Timers & counters used for internal state transitions
+ * \{
+ */
+ uint16_t m_dot11MeshMaxRetries;
+ Time m_dot11MeshRetryTimeout;
+ Time m_dot11MeshHoldingTimeout;
+ Time m_dot11MeshConfirmTimeout;
+
+ EventId m_retryTimer;
+ EventId m_holdingTimer;
+ EventId m_confirmTimer;
+ uint16_t m_retryCounter;
+ EventId m_beaconLossTimer;
+ uint16_t m_maxBeaconLoss;
+ //\}
+
+ /// ?
+ void BeaconLoss ();
+
+ /// How to report my status change
+ SignalStatusCallback m_linkStatusCallback;
+};
+
+} // namespace dot11s
+} //namespace ns3
+#endif /* PEERLLINK_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/peer-management-plugin.cc Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,246 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#include "ie-dot11s-configuration.h"
+#include "ie-dot11s-peer-management.h"
+#include "dot11s-mac-header.h"
+#include "peer-management-plugin.h"
+#include "peer-management-protocol.h"
+#include "peer-link-frame.h"
+#include "ns3/mesh-wifi-interface-mac.h"
+#include "ns3/simulator.h"
+#include "ns3/wifi-mac-header.h"
+
+namespace ns3 {
+namespace dot11s {
+PeerManagerMacPlugin::PeerManagerMacPlugin (uint32_t interface, Ptr<PeerManagementProtocol> protocol)
+{
+ m_ifIndex = interface;
+ m_protocol = protocol;
+}
+
+PeerManagerMacPlugin::~PeerManagerMacPlugin ()
+{
+}
+
+void
+PeerManagerMacPlugin::SetParent (Ptr<MeshWifiInterfaceMac> parent)
+{
+ m_parent = parent;
+}
+
+bool
+PeerManagerMacPlugin::Receive (Ptr<Packet> const_packet, const WifiMacHeader & header)
+{
+ // First of all we copy a packet, because we need to remove some
+ //headers
+ Ptr<Packet> packet = const_packet->Copy();
+ if(header.IsBeacon())
+ {
+ IeBeaconTiming beaconTiming;
+ Ptr<Packet> myBeacon = packet->Copy();
+ MgtBeaconHeader beacon_hdr;
+ myBeacon->RemoveHeader(beacon_hdr);
+ bool meshBeacon = false;
+ if(beaconTiming.FindFirst(myBeacon))
+ meshBeacon = true;
+ m_protocol->UpdatePeerBeaconTiming(
+ m_ifIndex,
+ meshBeacon,
+ beaconTiming,
+ header.GetAddr2(),
+ Simulator::Now(),
+ MicroSeconds(beacon_hdr.GetBeaconIntervalUs())
+ );
+ // Beacon shall not be dropeed. May be needed to another plugins
+ return true;
+ }
+ if(header.IsAction())
+ {
+ // TODO don't use this
+ Dot11sMacHeader meshHdr;
+ packet->RemoveHeader (meshHdr);
+ WifiMeshMultihopActionHeader multihopHdr;
+ //parse multihop action header:
+ packet->RemoveHeader (multihopHdr);
+ WifiMeshMultihopActionHeader::ActionValue actionValue = multihopHdr.GetAction ();
+ // If can not handle - just return;
+ if(multihopHdr.GetCategory () != WifiMeshMultihopActionHeader::MESH_PEER_LINK_MGT)
+ return true;
+ NS_ASSERT(meshHdr.GetMeshTtl () == 1);
+ NS_ASSERT(meshHdr.GetAddressExt () == 1);
+ Mac48Address peerAddress = header.GetAddr2 ();
+ Mac48Address peerMpAddress = meshHdr.GetAddr4 ();
+ PeerLinkFrameStart::PlinkFrameStartFields fields;
+ {
+ PeerLinkFrameStart peerFrame;
+ peerFrame.SetPlinkFrameSubtype((uint8_t)actionValue.peerLink);
+ packet->RemoveHeader (peerFrame);
+ fields = peerFrame.GetFields();
+ NS_ASSERT(fields.subtype == actionValue.peerLink);
+ }
+ if (actionValue.peerLink != WifiMeshMultihopActionHeader::PEER_LINK_CLOSE)
+ {
+ if(!(m_parent->CheckSupportedRates(fields.rates)))
+ {
+ m_protocol->ConfigurationMismatch (m_ifIndex, peerAddress);
+ // Broken peer link frame - drop it
+ return false;
+ }
+ if (!fields.meshId.IsEqual(m_parent->GetSsid()))
+ {
+ m_protocol->ConfigurationMismatch (m_ifIndex, peerAddress);
+ // Broken peer link frame - drop it
+ return false;
+ }
+ }
+ // MeshConfiguration Element - exists in all peer link management
+ // frames except CLOSE
+ IeConfiguration meshConfig;
+ if(fields.subtype != (uint8_t)(WifiMeshMultihopActionHeader::PEER_LINK_CLOSE))
+ {
+ packet->RemoveHeader(meshConfig);
+ }
+ IePeerManagement peerElement;
+ packet->RemoveHeader(peerElement);
+ //Check taht frame subtype corresponds peer link subtype
+ if(peerElement.SubtypeIsOpen ())
+ {
+ NS_ASSERT(actionValue.peerLink == WifiMeshMultihopActionHeader::PEER_LINK_OPEN);
+ }
+ if(peerElement.SubtypeIsConfirm ())
+ {
+ NS_ASSERT(actionValue.peerLink == WifiMeshMultihopActionHeader::PEER_LINK_CONFIRM);
+ }
+ if(peerElement.SubtypeIsClose ())
+ {
+ NS_ASSERT(actionValue.peerLink == WifiMeshMultihopActionHeader::PEER_LINK_CLOSE);
+ }
+ //Deliver Peer link management frame to protocol:
+ m_protocol->ReceivePeerLinkFrame(m_ifIndex, peerAddress, peerMpAddress, fields.aid, peerElement, meshConfig);
+ // if we can handle a frame - drop it
+ return false;
+ }
+ return m_protocol->IsActiveLink(m_ifIndex,header.GetAddr2());
+}
+
+bool
+PeerManagerMacPlugin::UpdateOutcomingFrame (Ptr<Packet> packet, WifiMacHeader & header, Mac48Address from, Mac48Address to) const
+{
+ return true;
+}
+
+void
+PeerManagerMacPlugin::UpdateBeacon (MeshWifiBeacon & beacon) const
+{
+ Ptr<IeBeaconTiming> beaconTiming = m_protocol->GetBeaconTimingElement(m_ifIndex);
+ beacon.AddInformationElement(beaconTiming);
+}
+
+void
+PeerManagerMacPlugin::SendPeerLinkManagementFrame(
+ Mac48Address peerAddress,
+ Mac48Address peerMpAddress,
+ uint16_t aid,
+ IePeerManagement peerElement,
+ IeConfiguration meshConfig
+ )
+{
+ //Create a packet:
+ Ptr<Packet> packet = Create<Packet> ();
+ packet->AddHeader (peerElement);
+ if(!peerElement.SubtypeIsClose())
+ packet->AddHeader (meshConfig);
+ PeerLinkFrameStart::PlinkFrameStartFields fields;
+ fields.rates = m_parent->GetSupportedRates ();
+ fields.meshId = m_parent->GetSsid ();
+ PeerLinkFrameStart plinkFrame;
+ //Create an 802.11 frame header:
+ //Send management frame to MAC:
+ WifiMeshMultihopActionHeader multihopHdr;
+ if (peerElement.SubtypeIsOpen ())
+ {
+ WifiMeshMultihopActionHeader::ActionValue action;
+ action.peerLink = WifiMeshMultihopActionHeader::PEER_LINK_OPEN;
+ fields.subtype = WifiMeshMultihopActionHeader::PEER_LINK_OPEN;
+ multihopHdr.SetAction (WifiMeshMultihopActionHeader::MESH_PEER_LINK_MGT, action);
+ }
+ if (peerElement.SubtypeIsConfirm ())
+ {
+ WifiMeshMultihopActionHeader::ActionValue action;
+ action.peerLink = WifiMeshMultihopActionHeader::PEER_LINK_CONFIRM;
+ fields.aid = aid;
+ fields.subtype = WifiMeshMultihopActionHeader::PEER_LINK_CONFIRM;
+ multihopHdr.SetAction (WifiMeshMultihopActionHeader::MESH_PEER_LINK_MGT, action);
+ }
+ if (peerElement.SubtypeIsClose ())
+ {
+ WifiMeshMultihopActionHeader::ActionValue action;
+ action.peerLink = WifiMeshMultihopActionHeader::PEER_LINK_CLOSE;
+ fields.subtype = WifiMeshMultihopActionHeader::PEER_LINK_CLOSE;
+ fields.reasonCode = peerElement.GetReasonCode ();
+ multihopHdr.SetAction (WifiMeshMultihopActionHeader::MESH_PEER_LINK_MGT, action);
+ }
+ plinkFrame.SetPlinkFrameStart(fields);
+ packet->AddHeader (plinkFrame);
+ packet->AddHeader (multihopHdr);
+ //mesh header:
+ // TODO don't use me
+ Dot11sMacHeader meshHdr;
+ meshHdr.SetMeshTtl (1);
+ meshHdr.SetMeshSeqno (0);
+ meshHdr.SetAddressExt(1);
+ meshHdr.SetAddr4(m_protocol->GetAddress ());
+ packet->AddHeader (meshHdr);
+ // Wifi Mac header:
+ WifiMacHeader hdr;
+ hdr.SetAction ();
+ hdr.SetAddr1 (peerAddress);
+ hdr.SetAddr2 (m_parent->GetAddress ());
+ hdr.SetAddr3 (peerMpAddress);
+ hdr.SetDsNotFrom ();
+ hdr.SetDsNotTo ();
+ m_parent->SendManagementFrame(packet, hdr);
+}
+
+Mac48Address
+PeerManagerMacPlugin::GetAddress () const
+{
+ if(m_parent != 0)
+ return m_parent->GetAddress ();
+ else return Mac48Address::Mac48Address();
+}
+std::pair<Time, Time>
+PeerManagerMacPlugin::GetBeaconInfo() const
+{
+ std::pair<Time,Time> retval;
+ retval.first = m_parent->GetTbtt ();
+ retval.second = m_parent->GetBeaconInterval ();
+ return retval;
+}
+void
+PeerManagerMacPlugin::SetBeaconShift(Time shift)
+{
+ m_parent->ShiftTbtt (shift);
+}
+
+} // namespace dot11s
+} //namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/peer-management-plugin.h Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,105 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#ifndef PEER_MANAGER_MAC_PLUGIN_H_
+#define PEER_MANAGER_MAC_PLUGIN_H_
+
+#include "ns3/mesh-wifi-interface-mac-plugin.h"
+
+namespace ns3 {
+class MeshWifiInterfaceMac;
+namespace dot11s {
+class PeerManagementProtocol;
+class IeConfiguration;
+class IePeerManagement;
+class PeerManagementProtocol;
+/**
+ * \ingroup dot11s
+ *
+ * \brief This is plugin to Mesh WiFi MAC, which implements
+ * interface to dot11s peer management protocol: it takes proper
+ * frames from MAC-layer, extracts peer link management information
+ * element and mesh configuration element and passes it to main part
+ * of protocol
+ */
+class PeerManagerMacPlugin : public MeshWifiInterfaceMacPlugin
+{
+public:
+ PeerManagerMacPlugin (uint32_t interface, Ptr<PeerManagementProtocol> protocol);
+ ~PeerManagerMacPlugin ();
+ ///\name Inherited from plugin abstract class
+ ///\{
+ void SetParent (Ptr<MeshWifiInterfaceMac> parent);
+ bool Receive (Ptr<Packet> packet, const WifiMacHeader & header);
+ bool UpdateOutcomingFrame (Ptr<Packet> packet, WifiMacHeader & header, Mac48Address from, Mac48Address to) const;
+ void UpdateBeacon (MeshWifiBeacon & beacon) const;
+ ///\}
+private:
+ friend class PeerManagementProtocol;
+ friend class PeerLink;
+ ///\name BCA functionallity:
+ ///\{
+ ///\brief Fills TBTT and beacon interval. Needed by BCA
+ ///functionallity
+ ///\param first in retval is TBTT
+ ///\param second in retval is beacon interval
+ std::pair<Time, Time> GetBeaconInfo() const;
+ void SetBeaconShift(Time shift);
+ ///\}
+ void SetPeerManagerProtcol(Ptr<PeerManagementProtocol> protocol);
+ void SendPeerLinkManagementFrame(
+ Mac48Address peerAddress,
+ Mac48Address peerMpAddress,
+ uint16_t aid,
+ IePeerManagement peerElement,
+ IeConfiguration meshConfig
+ );
+ ///\brief DUBUG only - to print established links
+ Mac48Address GetAddress () const;
+private:
+ ///\name Information about MAC and protocol:
+ ///\{
+ Ptr<MeshWifiInterfaceMac> m_parent;
+ uint32_t m_ifIndex;
+ Ptr<PeerManagementProtocol> m_protocol;
+ ///\}
+ ///\name Create peer link management frames:
+ ///\{
+ Ptr<Packet> CreatePeerLinkOpenFrame();
+ Ptr<Packet> CreatePeerLinkConfirmFrame();
+ Ptr<Packet> CreatePeerLinkCloseFrame();
+ ///This structure keeps all fields in peer link management frame,
+ ///which are not subclasses of WifiInformationElement
+ struct PlinkFrameStart {
+ uint8_t subtype;
+ uint16_t aid;
+ SupportedRates rates;
+ uint16_t qos;
+ };
+ /// \name Parses the start of the frame, where there are no
+ /// WifiInformationElements exist
+ PlinkFrameStart ParsePlinkFrame(Ptr<const Packet> packet);
+ ///\}
+};
+
+} // namespace dot11s
+} //namespace ns3
+#endif
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/peer-management-protocol.cc Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,497 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ * Aleksey Kovalenko <kovalenko@iitp.ru>
+ */
+
+
+#include "peer-management-protocol.h"
+
+#include "ie-dot11s-peer-management.h"
+#include "ie-dot11s-configuration.h"
+
+#include "ns3/mesh-point-device.h"
+#include "ns3/simulator.h"
+#include "ns3/assert.h"
+#include "ns3/log.h"
+#include "ns3/random-variable.h"
+#include "ns3/mesh-wifi-interface-mac.h"
+#include "ns3/mesh-wifi-interface-mac-plugin.h"
+#include "ns3/wifi-net-device.h"
+#include "peer-link.h"
+#include "peer-management-plugin.h"
+
+
+NS_LOG_COMPONENT_DEFINE ("PeerManagementProtocol");
+namespace ns3 {
+namespace dot11s {
+/***************************************************
+ * PeerManager
+ ***************************************************/
+NS_OBJECT_ENSURE_REGISTERED (PeerManagementProtocol);
+
+TypeId
+PeerManagementProtocol::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::dot11s::PeerManagementProtocol")
+ .SetParent<Object> ()
+ .AddConstructor<PeerManagementProtocol> ()
+ // peerLinkCleanupTimeout. We go through the map of peer links and
+ // remove all links which state is IDLE.
+ .AddAttribute ("PeerLinkCleanupPeriod",
+ "Idle peer link collection interval",
+ TimeValue (MilliSeconds (80)),
+ MakeTimeAccessor (&PeerManagementProtocol::m_peerLinkCleanupPeriod),
+ MakeTimeChecker ()
+ )
+ // maximum number of peer links. Now we calculate the total
+ // number of peer links on all interfaces
+ .AddAttribute ("MaxNumberOfPeerLinks",
+ "Maximum number of peer links",
+ UintegerValue (32),
+ MakeUintegerAccessor (&PeerManagementProtocol::m_maxNumberOfPeerLinks),
+ MakeUintegerChecker<uint8_t> ()
+ );
+ return tid;
+}
+PeerManagementProtocol::PeerManagementProtocol ():
+ m_lastAssocId (0),
+ m_lastLocalLinkId (1),
+ m_numberOfActivePeers (0)
+{
+ m_cleanupEvent = Simulator::Schedule (m_peerLinkCleanupPeriod, &PeerManagementProtocol::PeerCleanup, this);
+}
+PeerManagementProtocol::~PeerManagementProtocol ()
+{
+ //cancel cleanup event and go through the map of peer links,
+ //deleting each
+ m_cleanupEvent.Cancel ();
+ for (PeerLinksMap::iterator j = m_peerLinks.begin (); j != m_peerLinks.end (); j++)
+ {
+ for (PeerLinksOnInterface::iterator i = j->second.begin (); i != j->second.end(); i++)
+ {
+ (*i)->ClearTimingElement ();
+ (*i) = 0;
+ }
+ j->second.clear ();
+ }
+ m_peerLinks.clear ();
+ //cleaning beacon structures:
+ for(BeaconInfoMap::iterator i = m_neighbourBeacons.begin(); i != m_neighbourBeacons.end(); i ++)
+ {
+ i->second.clear();
+ }
+ m_neighbourBeacons.clear();
+}
+
+bool
+PeerManagementProtocol::Install(Ptr<MeshPointDevice> mp)
+{
+ std::vector<Ptr<NetDevice> > interfaces = mp->GetInterfaces ();
+ for(std::vector<Ptr<NetDevice> >::iterator i = interfaces.begin(); i != interfaces.end(); i ++)
+ {
+ const WifiNetDevice * wifiNetDev = dynamic_cast<const WifiNetDevice *> (PeekPointer (*i));
+ if (wifiNetDev == NULL)
+ return false;
+ MeshWifiInterfaceMac * mac = dynamic_cast<MeshWifiInterfaceMac *> (PeekPointer (wifiNetDev->GetMac ()));
+ if (mac == NULL)
+ return false;
+ Ptr<PeerManagerMacPlugin> peerPlugin = Create<PeerManagerMacPlugin> ((*i)->GetIfIndex(), this);
+ mac->InstallPlugin(peerPlugin);
+ m_plugins[(*i)->GetIfIndex()] = peerPlugin;
+ PeerLinksOnInterface newmap;
+ m_peerLinks[(*i)->GetIfIndex()] = newmap;
+ }
+ // Mesh point aggregates all installed protocols
+ m_address = Mac48Address::ConvertFrom(mp->GetAddress ());
+ NS_LOG_UNCOND("MP address:"<<m_address);
+ mp->AggregateObject(this);
+ return true;
+}
+
+Ptr<IeBeaconTiming>
+PeerManagementProtocol::GetBeaconTimingElement(uint32_t interface)
+{
+ Ptr<IeBeaconTiming> retval = Create<IeBeaconTiming> ();
+ BeaconInfoMap::iterator i = m_neighbourBeacons.find(interface);
+ if(i == m_neighbourBeacons.end())
+ return retval;
+ bool cleaned = false;
+ while(!cleaned)
+ {
+ for(BeaconsOnInterface::iterator j = i->second.begin(); j != i->second.end(); j++)
+ {
+ //check beacon loss and make a timing element
+ //if last beacon was 3 beacons ago - we do not put it to the
+ //timing element
+ if(
+ (j->second.referenceTbtt.GetMicroSeconds() +
+ (j->second.beaconInterval.GetMicroSeconds()* 3))
+ <
+ Simulator::Now().GetMicroSeconds()
+ )
+ {
+ i->second.erase(j);
+ break;
+ }
+ }
+ cleaned = true;
+ }
+ for(BeaconsOnInterface::const_iterator j = i->second.begin(); j != i->second.end(); j++)
+ retval->AddNeighboursTimingElementUnit(j->second.aid, j->second.referenceTbtt, j->second.beaconInterval);
+ return retval;
+}
+
+void
+PeerManagementProtocol::FillBeaconInfo(uint32_t interface, Mac48Address peerAddress, Time receivingTime, Time beaconInterval)
+{
+ BeaconInfoMap::iterator i = m_neighbourBeacons.find(interface);
+ if(i == m_neighbourBeacons.end())
+ {
+ BeaconsOnInterface newMap;
+ m_neighbourBeacons[interface] = newMap;
+ }
+ i = m_neighbourBeacons.find(interface);
+ BeaconsOnInterface::iterator j = i->second.find(peerAddress);
+ if(j == i->second.end())
+ {
+ BeaconInfo newInfo;
+ newInfo.referenceTbtt = receivingTime;
+ newInfo.beaconInterval = beaconInterval;
+ newInfo.aid = m_lastAssocId++;
+ if(m_lastAssocId == 0xff)
+ m_lastAssocId = 0;
+ i->second[peerAddress] = newInfo;
+ }
+ else
+ {
+ j->second.referenceTbtt = receivingTime;
+ j->second.beaconInterval = beaconInterval;
+ }
+}
+
+void
+PeerManagementProtocol::UpdatePeerBeaconTiming(
+ uint32_t interface,
+ bool meshBeacon,
+ IeBeaconTiming timingElement,
+ Mac48Address peerAddress,
+ Time receivingTime,
+ Time beaconInterval)
+{
+ FillBeaconInfo(interface, peerAddress, receivingTime, beaconInterval);
+ if(!meshBeacon)
+ return;
+ //BCA:
+ PeerManagerPluginMap::iterator plugin = m_plugins.find (interface);
+ NS_ASSERT(plugin != m_plugins.end ());
+ plugin->second->SetBeaconShift(GetNextBeaconShift(interface));
+ //PM STATE Machine
+ //Check that a given beacon is not from our interface
+ for(PeerManagerPluginMap::const_iterator i = m_plugins.begin (); i != m_plugins.end (); i ++)
+ if(i->second->GetAddress () == peerAddress)
+ return;
+ Ptr<PeerLink> peerLink = FindPeerLink(interface, peerAddress);
+ if(peerLink !=0)
+ {
+ peerLink->SetBeaconTimingElement (timingElement);
+ peerLink->SetBeaconInformation (receivingTime, beaconInterval);
+ }
+ else
+ {
+ peerLink = InitiateLink (interface, peerAddress, Mac48Address::GetBroadcast (), receivingTime, beaconInterval);
+ peerLink->SetBeaconTimingElement (timingElement);
+ if (ShouldSendOpen (interface, peerAddress))
+ peerLink->MLMEActivePeerLinkOpen ();
+ }
+}
+
+void
+PeerManagementProtocol::ReceivePeerLinkFrame (
+ uint32_t interface,
+ Mac48Address peerAddress,
+ Mac48Address peerMeshPointAddress,
+ uint16_t aid,
+ IePeerManagement peerManagementElement,
+ IeConfiguration meshConfig
+ )
+{
+ Ptr<PeerLink> peerLink = FindPeerLink(interface, peerAddress);
+ if (peerManagementElement.SubtypeIsOpen ())
+ {
+ PmpReasonCode reasonCode;
+ bool reject = ! (ShouldAcceptOpen (interface, peerAddress,reasonCode));
+ if (peerLink == 0)
+ peerLink = InitiateLink (interface, peerAddress, peerMeshPointAddress, Simulator::Now (), Seconds(1.0));
+ if(!reject)
+ {
+ peerLink->MLMEPassivePeerLinkOpen ();
+ peerLink->OpenAccept (peerManagementElement.GetLocalLinkId(), meshConfig, peerMeshPointAddress);
+ }
+ else
+ peerLink->OpenReject (peerManagementElement.GetLocalLinkId(), meshConfig, peerMeshPointAddress, reasonCode);
+ }
+ if (peerLink == 0)
+ return;
+ if (peerManagementElement.SubtypeIsConfirm ())
+ peerLink->ConfirmAccept (
+ peerManagementElement.GetLocalLinkId(),
+ peerManagementElement.GetPeerLinkId(),
+ aid,
+ meshConfig,
+ peerMeshPointAddress);
+ if (peerManagementElement.SubtypeIsClose ())
+ peerLink->Close (
+ peerManagementElement.GetLocalLinkId(),
+ peerManagementElement.GetPeerLinkId(),
+ peerManagementElement.GetReasonCode()
+ );
+}
+
+void
+PeerManagementProtocol::ConfigurationMismatch (uint32_t interface, Mac48Address peerAddress)
+{
+ Ptr<PeerLink> peerLink = FindPeerLink(interface, peerAddress);
+ if(peerLink != 0)
+ peerLink->MLMECancelPeerLink (REASON11S_MESH_CONFIGURATION_POLICY_VIOLATION);
+}
+
+Ptr<PeerLink>
+PeerManagementProtocol::InitiateLink (
+ uint32_t interface,
+ Mac48Address peerAddress,
+ Mac48Address peerMeshPointAddress,
+ Time lastBeacon,
+ Time beaconInterval)
+{
+ Ptr<PeerLink> new_link = CreateObject<PeerLink> ();
+ if (m_lastLocalLinkId == 0xff)
+ m_lastLocalLinkId = 0;
+ //find a beacon entry
+ BeaconInfoMap::iterator beaconsOnInterface = m_neighbourBeacons.find (interface);
+ if(beaconsOnInterface == m_neighbourBeacons.end())
+ FillBeaconInfo(interface, peerAddress, lastBeacon, beaconInterval);
+ beaconsOnInterface = m_neighbourBeacons.find (interface);
+ BeaconsOnInterface::iterator beacon = beaconsOnInterface->second.find (peerAddress);
+ if(beacon == beaconsOnInterface->second.end ())
+ FillBeaconInfo(interface, peerAddress, lastBeacon, beaconInterval);
+ beacon = beaconsOnInterface->second.find (peerAddress);
+ //find a peer link - it must not exist
+ if(FindPeerLink(interface, peerAddress) != 0)
+ {
+ NS_ASSERT (false);
+ }
+ // Plugin must exist
+ PeerManagerPluginMap::iterator plugin = m_plugins.find (interface);
+ NS_ASSERT(plugin != m_plugins.end ());
+ PeerLinksMap::iterator iface = m_peerLinks.find (interface);
+ NS_ASSERT (iface != m_peerLinks.end());
+ new_link->SetLocalAid (beacon->second.aid);
+ new_link->SetInterface (interface);
+ new_link->SetLocalLinkId (m_lastLocalLinkId++);
+ new_link->SetPeerAddress (peerAddress);
+ new_link->SetPeerMeshPointAddress (peerMeshPointAddress);
+ new_link->SetBeaconInformation (lastBeacon, beaconInterval);
+ new_link->SetMacPlugin (plugin->second);
+ new_link->MLMESetSignalStatusCallback (MakeCallback(&PeerManagementProtocol::PeerLinkStatus, this));
+ iface->second.push_back (new_link);
+ return new_link;
+}
+Ptr<PeerLink>
+PeerManagementProtocol::FindPeerLink(uint32_t interface, Mac48Address peerAddress)
+{
+ PeerLinksMap::iterator iface = m_peerLinks.find (interface);
+ NS_ASSERT (iface != m_peerLinks.end());
+ for (PeerLinksOnInterface::iterator i = iface->second.begin (); i != iface->second.end(); i++)
+ if ((*i)->GetPeerAddress () == peerAddress)
+ return (*i);
+ return 0;
+}
+void
+PeerManagementProtocol::SetPeerLinkStatusCallback(Callback <void, Mac48Address, Mac48Address, uint32_t, bool> cb)
+{
+ m_peerStatusCallback = cb;
+}
+std::vector<Mac48Address>
+PeerManagementProtocol::GetActiveLinks(uint32_t interface)
+{
+ std::vector<Mac48Address> retval;
+ PeerLinksMap::iterator iface = m_peerLinks.find (interface);
+ NS_ASSERT (iface != m_peerLinks.end());
+ for (PeerLinksOnInterface::iterator i = iface->second.begin (); i != iface->second.end(); i++)
+ if((*i)->LinkIsEstab ())
+ retval.push_back((*i)->GetPeerAddress ());
+ return retval;
+}
+void
+PeerManagementProtocol::PeerCleanup ()
+{
+ //Cleanup a peer link descriptors:
+ for (
+ PeerLinksMap::iterator j = m_peerLinks.begin ();
+ j != m_peerLinks.end ();
+ j++)
+ {
+ std::vector<unsigned int> to_erase;
+ for (unsigned int i = 0; i< j->second.size (); i++)
+ if (j->second[i]->LinkIsIdle ())
+ {
+ j->second[i]->ClearTimingElement ();
+ j->second[i] = 0;
+ to_erase.push_back (i);
+ }
+ if (to_erase.size () == 0)
+ return;
+ for (unsigned int i = to_erase.size ()-1 ; i >= 0; i--)
+ j->second.erase (j->second.begin() + to_erase[i]);
+ to_erase.clear ();
+ }
+ // cleanup neighbour beacons:
+ m_cleanupEvent = Simulator::Schedule (m_peerLinkCleanupPeriod, &PeerManagementProtocol::PeerCleanup, this);
+}
+bool
+PeerManagementProtocol::IsActiveLink (uint32_t interface, Mac48Address peerAddress)
+{
+ Ptr<PeerLink> peerLink = FindPeerLink(interface, peerAddress);
+ if(peerLink != 0)
+ return (peerLink->LinkIsEstab ());
+ return false;
+}
+bool
+PeerManagementProtocol::ShouldSendOpen (uint32_t interface, Mac48Address peerAddress)
+{
+ if (m_numberOfActivePeers > m_maxNumberOfPeerLinks)
+ return false;
+ return true;
+}
+bool
+PeerManagementProtocol::ShouldAcceptOpen (
+ uint32_t interface,
+ Mac48Address peerAddress,
+ PmpReasonCode & reasonCode)
+{
+ if (m_numberOfActivePeers > m_maxNumberOfPeerLinks)
+ {
+ reasonCode = REASON11S_MESH_MAX_PEERS;
+ return false;
+ }
+ return true;
+}
+Time
+PeerManagementProtocol::GetNextBeaconShift (uint32_t interface)
+{
+ //REMINDER:: in timing element 1) last beacon reception time is measured in units of 256 microseconds
+ // 2) beacon interval is mesured in units of 1024 microseconds
+ // 3) hereafter TU = 1024 microseconds
+ //Im my MAC everything is stored in MicroSeconds
+
+ uint32_t myNextTbttInTimeUnits = Simulator::Now().GetMicroSeconds();
+ uint32_t futureBeaconInTimeUnits = 0;
+ //Going through all my timing elements and detecting future beacon collisions
+ PeerLinksMap::iterator iface = m_peerLinks.find (interface);
+ NS_ASSERT (iface != m_peerLinks.end());
+ PeerManagerPluginMap::iterator plugin = m_plugins.find (interface);
+ NS_ASSERT(plugin != m_plugins.end());
+ std::pair<Time, Time> myBeacon = plugin->second->GetBeaconInfo ();
+ for (PeerLinksOnInterface::iterator i = iface->second.begin (); i != iface->second.end (); i++)
+ {
+ IeBeaconTiming::NeighboursTimingUnitsList neighbours;
+ neighbours = (*i)->GetBeaconTimingElement ().GetNeighboursTimingElementsList();
+ //first let's form the list of all kown Tbtts
+ for (IeBeaconTiming::NeighboursTimingUnitsList::const_iterator j = neighbours.begin (); j != neighbours.end(); j++)
+ {
+ uint16_t beaconIntervalTimeUnits;
+ beaconIntervalTimeUnits = (*j)->GetBeaconInterval ();
+ //The last beacon time in timing elememt in Time Units
+ uint32_t lastBeaconInTimeUnits;
+ lastBeaconInTimeUnits = (*j)->GetLastBeacon ()/4;
+ //The time of my next beacon sending in Time Units
+ myNextTbttInTimeUnits = myBeacon.first.GetMicroSeconds ()/1024;
+ //My beacon interval in Time Units
+ uint32_t myBeaconIntervalInTimeUnits;
+ myBeaconIntervalInTimeUnits = myBeacon.second.GetMicroSeconds ()/1024;
+ //The time the beacon of other station will be sent
+ //we need the time just after my next Tbtt (or equal to my Tbtt)
+ futureBeaconInTimeUnits = lastBeaconInTimeUnits + beaconIntervalTimeUnits;
+ //We apply MBAC only if beacon Intervals are equal
+ if (beaconIntervalTimeUnits == myBeaconIntervalInTimeUnits)
+ {
+ //We know when the neighbor STA transmitted it's beacon
+ //Now we need to know when it's going to send it's beacon in the future
+ //So let's use the valuse of it's beacon interval
+ while (myNextTbttInTimeUnits >= futureBeaconInTimeUnits)
+ futureBeaconInTimeUnits = futureBeaconInTimeUnits + beaconIntervalTimeUnits;
+ //If we found that my Tbtt coincide with another STA's Tbtt
+ //break all cylce and return time shift for my next Tbtt
+ if (myNextTbttInTimeUnits == futureBeaconInTimeUnits)
+ break;
+ }
+ }
+ if (myNextTbttInTimeUnits == futureBeaconInTimeUnits)
+ break;
+ }
+ //Tbtts coincide, so let's calculate the shift
+ if (myNextTbttInTimeUnits == futureBeaconInTimeUnits)
+ {
+ NS_LOG_DEBUG ("MBCA: Future beacon collision is detected, applying avoidance mechanism");
+ UniformVariable randomSign (-1, 1);
+ int coefficientSign = -1;
+ if (randomSign.GetValue () >= 0)
+ coefficientSign = 1;
+ UniformVariable randomShift (1, 15);
+ //So, the shift is a random integer variable uniformly distributed in [-15;-1] U [1;15]
+ int beaconShift = randomShift.GetInteger (1,15) * coefficientSign;
+ NS_LOG_DEBUG ("Shift value = " << beaconShift << " beacon TUs");
+ //We need the result not in Time Units, but in microseconds
+ //Do not shift to the past
+ if(MicroSeconds(beaconShift * 1024) + Simulator::Now() < myBeacon.first)
+ return MicroSeconds (beaconShift * 1024);
+ else
+ return MicroSeconds (0);
+ }
+ //No collision detected, hence no shift is needed
+ else
+ return MicroSeconds (0);
+}
+void
+PeerManagementProtocol::PeerLinkStatus (uint32_t interface, Mac48Address peerAddress, Mac48Address peerMeshPointAddress, bool status)
+{
+ PeerManagerPluginMap::iterator plugin = m_plugins.find (interface);
+ NS_ASSERT(plugin != m_plugins.end());
+ NS_LOG_DEBUG(
+ "Link between me:" << m_address <<
+ " my interface:" << plugin->second->GetAddress() <<
+ " and peer mesh point:" << peerMeshPointAddress <<
+ " and its interface:" << peerAddress <<
+ ", at my interface ID:" << interface <<
+ ". Status:" << status);
+ if(status)
+ m_numberOfActivePeers ++;
+ else
+ m_numberOfActivePeers --;
+ if(!m_peerStatusCallback.IsNull ())
+ m_peerStatusCallback (peerMeshPointAddress, peerAddress, interface, status);
+}
+Mac48Address
+PeerManagementProtocol::GetAddress ()
+{
+ return m_address;
+}
+} // namespace dot11s
+} //namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/peer-management-protocol.h Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,230 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ * Aleksey Kovalenko <kovalenko@iitp.ru>
+ */
+
+
+#ifndef DOT11S_PEER_MAN_H
+#define DOT11S_PEER_MAN_H
+
+#include "ns3/mac48-address.h"
+#include "ns3/net-device.h"
+#include "ns3/event-id.h"
+#include "ns3/nstime.h"
+#include "ie-dot11s-beacon-timing.h"
+#include "ie-dot11s-peer-management.h"
+
+#include <map>
+namespace ns3 {
+class MeshPointDevice;
+namespace dot11s {
+class PeerManagerMacPlugin;
+class PeerLink;
+class IePeerManagement;
+class IeConfiguration;
+/**
+ * \ingroup dot11s
+ *
+ * \brief 802.11s Peer Management Protocol model
+ */
+class PeerManagementProtocol : public Object
+{
+public:
+ PeerManagementProtocol ();
+ ~PeerManagementProtocol ();
+ static TypeId GetTypeId ();
+ /**
+ * \brief Install PMP on given mesh point.
+ *
+ * Installing protocol cause installing its interface MAC plugins.
+ *
+ * Also MP aggregates all installed protocols, PMP protocol can be accessed
+ * via MeshPointDevice::GetObject<PeerManagementProtocol>();
+ */
+ bool Install(Ptr<MeshPointDevice>);
+ /**
+ * \brief Methods that handle beacon sending/receiving procedure.
+ *
+ * This methods interact with MAC_layer plug-in
+ * \{
+ */
+ /**
+ * \brief When we are sending a beacon - we fill beacon timing
+ * element
+ * \param IeBeaconTiming is a beacon timing element that
+ * should be present in beacon
+ * \param interface is a interface sending a beacon
+ */
+ Ptr<IeBeaconTiming> GetBeaconTimingElement(uint32_t interface);
+ /**
+ * \brief When we receive a beacon from peer-station, we remember
+ * its beacon timing element (needed for peer choosing mechanism),
+ * and remember beacon timers - last beacon and beacon interval to
+ * detect beacon loss and cancel links
+ * \param interface is a interface on which beacon was received
+ * \param timingElement is a timing element of remote beacon
+ */
+ void UpdatePeerBeaconTiming(
+ uint32_t interface,
+ bool meshBeacon,
+ IeBeaconTiming timingElement,
+ Mac48Address peerAddress,
+ Time receivingTime,
+ Time beaconInterval
+ );
+ //\}
+ /**
+ * \brief Methods that handle Peer link management frames
+ * interaction:
+ * \{
+ */
+ /**
+ * Deliver Peer link management information to the protocol-part
+ * \param void is returning value - we pass a frame and forget
+ * about it
+ * \param uint32_t - is a interface ID of a given MAC (interfaceID rather
+ * than MAC address, beacause many interfaces may have the same MAC)
+ * \param Mac48Address is address of peer
+ * \param Mac48Address is address of peer mesh point device (equal
+ * to peer address when only one interface)
+ * \param uint16_t is association ID, which peer has assigned to
+ * us
+ * \param IeConfiguration is mesh configuration element
+ * taken from the peer management frame
+ * \param IePeerManagement is peer link management element
+ */
+ void ReceivePeerLinkFrame(
+ uint32_t interface,
+ Mac48Address peerAddress,
+ Mac48Address peerMeshPointAddress,
+ uint16_t aid,
+ IePeerManagement peerManagementElement,
+ IeConfiguration meshConfig
+ );
+ /**
+ * Cancell peer link due to broken configuration (SSID or Supported
+ * rates)
+ */
+ void ConfigurationMismatch (uint32_t interface, Mac48Address peerAddress);
+ /**
+ * Checks if there is established link
+ */
+ bool IsActiveLink (uint32_t interface, Mac48Address peerAddress);
+ //\}
+ ///\brief Needed by external module to do MLME
+ Ptr<PeerLink> FindPeerLink(uint32_t interface, Mac48Address peerAddress);
+ void SetPeerLinkStatusCallback (Callback<void, Mac48Address, Mac48Address, uint32_t, bool> cb);
+ std::vector<Mac48Address> GetActiveLinks(uint32_t interface);
+ ///\brief needed by plugins to set global source address
+ Mac48Address GetAddress ();
+private:
+ /** \name Private structures
+ * \{
+ */
+ /// Keeps information about beacon of peer station: beacon interval, association ID, last time we have received a beacon
+ struct BeaconInfo
+ {
+ uint16_t aid; //Assoc ID
+ Time referenceTbtt; //When one of my station's beacons was put into a beacon queue;
+ Time beaconInterval; //Beacon interval of my station;
+ };
+ /// We keep a vector of pointers to PeerLink class. This vector
+ /// keeps all peer links at a given interface.
+ typedef std::vector<Ptr<PeerLink> > PeerLinksOnInterface;
+ /// This map keeps all peer links.
+ ///\param uint32_t is interface ID
+ typedef std::map<uint32_t, PeerLinksOnInterface> PeerLinksMap;
+ ///\brief This map keeps relationship between peer address and its
+ /// beacon information
+ typedef std::map<Mac48Address, BeaconInfo> BeaconsOnInterface;
+ ///\brief This map keeps beacon information on all intefaces
+ typedef std::map<uint32_t, BeaconsOnInterface> BeaconInfoMap;
+ ///\brief this vector keeps pointers to MAC-plugins
+ typedef std::map<uint32_t, Ptr<PeerManagerMacPlugin> > PeerManagerPluginMap;
+ ///\}
+private:
+ /**
+ * Return a position in beacon-storage for a given remote station
+ */
+ void FillBeaconInfo(uint32_t interface, Mac48Address peerAddress, Time receivingTime, Time beaconInterval);
+ Ptr<PeerLink> InitiateLink (
+ uint32_t interface,
+ Mac48Address peerAddress,
+ Mac48Address peerMeshPointAddress,
+ Time lastBeacon,
+ Time beaconInterval
+ );
+ /**
+ * \name External peer-chooser
+ * \{
+ */
+ bool ShouldSendOpen (uint32_t interface, Mac48Address peerAddress);
+ bool ShouldAcceptOpen (uint32_t interface, Mac48Address peerAddress, PmpReasonCode & reasonCode);
+ /**
+ * \}
+ * \brief Indicates changes in peer links
+ */
+ void PeerLinkStatus (uint32_t interface, Mac48Address peerAddress, Mac48Address peerMeshPointAddres, bool status);
+ /**
+ * Removes all links which are idle
+ */
+ void PeerCleanup ();
+ ///\brief BCA
+ Time GetNextBeaconShift (uint32_t interface);
+private:
+ PeerManagerPluginMap m_plugins;
+ Mac48Address m_address;
+ /**
+ * \name Information related to beacons:
+ * \{
+ */
+ BeaconInfoMap m_neighbourBeacons;
+ ///\}
+ uint16_t m_lastAssocId;
+ uint16_t m_lastLocalLinkId;
+ uint8_t m_numberOfActivePeers; //number of established peer links
+ uint8_t m_maxNumberOfPeerLinks;
+ /**
+ * Peer Links
+ * \{
+ */
+ PeerLinksMap m_peerLinks;
+ /**
+ * \}
+ */
+ /**
+ * Periodically we scan the peer manager list of peers
+ * and check if the too many beacons were lost:
+ * \{
+ */
+ Time m_peerLinkCleanupPeriod;
+ EventId m_cleanupEvent;
+ ///\}
+ ///\brief Callback to notify about peer link changes:
+ ///\param Mac48Address is peer address of mesh point
+ ///\param Mac48Address is peer address of interface
+ ///\param uint32_t - interface ID
+ ///\param bool is staus - true when new link has appeared, false -
+ //when link was closed
+ Callback <void, Mac48Address, Mac48Address, uint32_t, bool> m_peerStatusCallback;
+};
+
+} // namespace dot11s
+} //namespace ns3
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/waf Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,1 @@
+exec "`dirname "$0"`"/../../../../waf "$@"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/wscript Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,46 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+
+def build(bld):
+ obj = bld.create_ns3_module('dot11s', ['wifi'])
+ obj.source = [
+ 'ie-dot11s-beacon-timing.cc',
+ 'ie-dot11s-configuration.cc',
+ 'ie-dot11s-peer-management.cc',
+ 'ie-dot11s-preq.cc',
+ 'ie-dot11s-prep.cc',
+ 'ie-dot11s-perr.cc',
+ 'ie-dot11s-rann.cc',
+ 'dot11s-mac-header.cc',
+ 'peer-link-frame.cc',
+ 'peer-link.cc',
+ 'peer-management-plugin.cc',
+ 'peer-management-protocol.cc',
+ 'hwmp-tag.cc',
+ 'hwmp-rtable.cc',
+ 'hwmp-mac-plugin.cc',
+ 'hwmp-protocol.cc',
+ 'airtime-metric.cc',
+ 'dot11s-helper.cc',
+ ]
+ headers = bld.new_task_gen('ns3header')
+ headers.module = 'dot11s'
+ headers.source = [
+ 'ie-dot11s-beacon-timing.h',
+ #'ie-dot11s-configuration.h',
+ 'ie-dot11s-peer-management.h',
+ #'ie-dot11s-preq.h',
+ #'ie-dot11s-prep.h',
+ 'ie-dot11s-perr.h',
+ #'ie-dot11s-rann.h',
+ #'peer-link-frame.h',
+ #'peer-link.h',
+ #'peer-management-plugin.h',
+ 'peer-management-protocol.h',
+ #'hwmp-mac-plugin.h',
+ 'hwmp-protocol.h',
+ 'dot11s-helper.h',
+ ]
+
+# obj = bld.create_ns3_program('wifi-phy-test',
+# ['core', 'simulator', 'mobility', 'node', 'wifi'])
+# obj.source = 'wifi-phy-test.cc'
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/mesh-l2-routing-protocol.cc Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,55 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ * Pavel Boyko <boyko@iitp.ru>
+ */
+
+#include "ns3/log.h"
+#include "ns3/mesh-l2-routing-protocol.h"
+#include "ns3/mesh-point-device.h"
+
+NS_LOG_COMPONENT_DEFINE ("MeshL2RoutingProtocol");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (MeshL2RoutingProtocol);
+
+TypeId
+MeshL2RoutingProtocol::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::MeshL2RoutingProtocol")
+ .SetParent<Object> ();
+ return tid;
+}
+
+MeshL2RoutingProtocol::~MeshL2RoutingProtocol ()
+{
+}
+
+void
+MeshL2RoutingProtocol::SetMeshPoint (Ptr<MeshPointDevice> mp)
+{
+ m_mp = mp;
+}
+
+Ptr<MeshPointDevice> MeshL2RoutingProtocol::GetMeshPoint () const
+{
+ return m_mp;
+}
+
+} // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/mesh-l2-routing-protocol.h Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,132 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ * Pavel Boyko <boyko@iitp.ru>
+ */
+
+#ifndef MESH_L2_ROUTING_PROTOCOL_H
+#define MESH_L2_ROUTING_PROTOCOL_H
+
+#include "ns3/object.h"
+#include "ns3/mac48-address.h"
+
+namespace ns3 {
+
+class Packet;
+class MeshPointDevice;
+
+/**
+ * \ingroup mesh
+ *
+ * \brief Interface for L2 mesh routing protocol and mesh point communication.
+ *
+ * Every mesh routing protocol must implement this interface. Each mesh point (MeshPointDevice) is supposed
+ * to know single L2RoutingProtocol to work with, see MeshPointDevice::SetRoutingProtocol ().
+ *
+ * This interface is similar to ipv4 routiong protocol base class.
+ */
+class MeshL2RoutingProtocol : public Object
+{
+public:
+ /// Never forget to support NS3 object model
+ static TypeId GetTypeId ();
+ /// virtual D-tor for subclasses
+ virtual ~MeshL2RoutingProtocol ();
+ /**
+ * Callback to be invoked when route discovery procedure is completed.
+ *
+ * \param flag indicating whether a route was actually found and all needed information is
+ * added to the packet succesfully
+ *
+ * \param packet for which the route was resolved. All routing information for MAC layer
+ * must be stored in proper tags (like in case of HWMP, when WifiMacHeader
+ * needs address of next hop), or must be added as a packet header (if MAC
+ * does not need any additional information). So, the packet is returned back
+ * to MeshPointDevice looks like a pure packet with ethernet header
+ * (i.e data + src +dst + protocol). The only special information addressed
+ * to MeshPointDevice is an outcoming interface ID.
+ *
+ * \param src source address of the packet
+ *
+ * \param dst destiation address of the packet
+ *
+ * \param protocol ethernet 'Protocol' field, needed to form a proper MAC-layer header
+ *
+ * \param uint32_t outcoming interface to use or 0xffffffff if packet should be sent by ALL interfaces
+ */
+ typedef Callback<void,/* return type */
+ bool, /* flag */
+ Ptr<Packet>, /* packet */
+ Mac48Address,/* src */
+ Mac48Address,/* dst */
+ uint16_t, /* protocol */
+ uint32_t /* out interface ID */
+ > RouteReplyCallback;
+ /**
+ * Request routing information, all packets must go through this request.
+ *
+ * Note that route discobery works async. -- RequestRoute returns immediately, while
+ * reply callback will be called when routing information will be avaliable.
+ * \return true if valid route is already known
+ * \param sourceIface the incoming interface of the packet
+ * \param source source address
+ * \param destination destination address
+ * \param packet the packet to be resolved (needed the whole packet, because
+ * routing information is added as tags or headers). The packet
+ * will be retutned to reply callback.
+ * \param protocolType protocol ID, needed to form a proper MAC-layer header
+ * \param routeReply callback to be invoked after route discovery procedure, supposed
+ * to really send packetusing routing information.
+ */
+ virtual bool RequestRoute (uint32_t sourceIface, const Mac48Address source, const Mac48Address destination,
+ Ptr<Packet> packet, uint16_t protocolType, RouteReplyCallback routeReply ) = 0;
+ /// Set host mesh point, analog of SetNode (...) methods for upper layer protocols.
+ void SetMeshPoint (Ptr<MeshPointDevice> mp);
+ /// Each mesh protocol must be installed on the mesh point to work.
+ Ptr<MeshPointDevice> GetMeshPoint () const;
+protected:
+ ///\name Route request queue API, supposed to be implemented in subclasses
+ //\{
+ /// Packet waiting its routing inforamation, supposed to be used by all implementations to correctly implement timeouts.
+ struct QueuedPacket {
+ Ptr<Packet> pkt; ///< the packet
+ Mac48Address src; ///< src address
+ Mac48Address dst; ///< dst address
+ uint16_t protocol; ///< protocol number
+ uint32_t inInterface; ///< incoming device interface ID. (if packet has come from upper layers, this is Mesh point ID)
+ RouteReplyCallback reply; ///< how to reply
+ };
+ /**
+ * \brief Queue route request packet with 'Ethernet header'
+ * \return false if the queue is full.
+ */
+ virtual bool QueuePacket (struct QueuedPacket packet) = 0;
+ /**
+ * \brief Deque packet with 'Ethernet header'
+ * \param destination The destination address, which identifyes queue.
+ * \return Ptr<packet> (0 if queue is empty), src, dst, protocol ID, incoming port ID, and reply callback
+ */
+ virtual QueuedPacket DequeueFirstPacketByDst (Mac48Address destination) = 0;
+ virtual QueuedPacket DequeueFirstPacket () = 0;
+ //\}
+protected:
+ /// Host mesh point
+ Ptr<MeshPointDevice> m_mp;
+};
+}//namespace ns3
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/mesh-point-device.cc Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,375 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ * Pavel Boyko <boyko@iitp.ru>
+ */
+
+
+#include "ns3/node.h"
+#include "ns3/packet.h"
+#include "ns3/log.h"
+#include "ns3/pointer.h"
+#include "ns3/mesh-point-device.h"
+
+NS_LOG_COMPONENT_DEFINE ("MeshPointDevice");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (MeshPointDevice);
+
+TypeId
+MeshPointDevice::GetTypeId ()
+{
+ static TypeId tid = TypeId ("ns3::MeshPointDevice")
+ .SetParent<NetDevice> ()
+ .AddConstructor<MeshPointDevice> ()
+ .AddAttribute ("RoutingProtocol", "The mesh routing protocol used by this mesh point.",
+ PointerValue (),
+ MakePointerAccessor (&MeshPointDevice::GetRoutingProtocol,
+ &MeshPointDevice::SetRoutingProtocol),
+ MakePointerChecker<MeshL2RoutingProtocol> ())
+ ;
+ return tid;
+}
+
+MeshPointDevice::MeshPointDevice () : m_ifIndex (0), m_mtu(1500)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_channel = CreateObject<BridgeChannel> ();
+}
+
+MeshPointDevice::~MeshPointDevice ()
+{
+ NS_LOG_FUNCTION_NOARGS ();
+}
+
+void
+MeshPointDevice::DoDispose ()
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ for (std::vector< Ptr<NetDevice> >::iterator iter = m_ifaces.begin (); iter != m_ifaces.end (); iter++)
+ *iter = 0;
+ m_ifaces.clear ();
+ m_node = 0;
+ NetDevice::DoDispose ();
+
+}
+
+//-----------------------------------------------------------------------------
+// NetDevice interface implementation
+//-----------------------------------------------------------------------------
+
+void
+MeshPointDevice::ReceiveFromDevice (Ptr<NetDevice> incomingPort, Ptr<const Packet> packet, uint16_t protocol,
+ Address const &src, Address const &dst, PacketType packetType)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_DEBUG ("UID is " << packet->GetUid ());
+ const Mac48Address src48 = Mac48Address::ConvertFrom (src);
+ const Mac48Address dst48 = Mac48Address::ConvertFrom (dst);
+ NS_LOG_DEBUG ("SRC="<<src48<<", DST = "<<dst48<<", I am: "<<m_address);
+ if (!m_promiscRxCallback.IsNull ())
+ m_promiscRxCallback (this, packet, protocol, src, dst, packetType);
+ if(dst48.IsBroadcast () || dst48.IsMulticast ())
+ {
+ m_rxCallback (this, packet, protocol, src);
+ Forward (incomingPort, packet->Copy (), protocol, src48, dst48);
+ return;
+ }
+ if(dst48 == m_address)
+ m_rxCallback (this, packet, protocol, src);
+ else
+ Forward (incomingPort, packet->Copy (), protocol, src48, dst48);
+}
+
+void
+MeshPointDevice::Forward (Ptr<NetDevice> inport, Ptr<Packet> packet,
+ uint16_t protocol, const Mac48Address src, const Mac48Address dst)
+{
+ // pass through routing protocol
+ m_requestRoute (inport->GetIfIndex(), src, dst, packet, protocol, m_myResponse);
+}
+
+void
+MeshPointDevice::SetName (const std::string name)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_name = name;
+}
+
+std::string
+MeshPointDevice::GetName () const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_name;
+}
+
+void
+MeshPointDevice::SetIfIndex (const uint32_t index)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_ifIndex = index;
+}
+
+uint32_t
+MeshPointDevice::GetIfIndex () const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_ifIndex;
+}
+
+Ptr<Channel>
+MeshPointDevice::GetChannel () const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_channel;
+}
+
+Address
+MeshPointDevice::GetAddress () const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_address;
+}
+
+bool
+MeshPointDevice::SetMtu (const uint16_t mtu)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_mtu = mtu;
+ return true;
+}
+
+uint16_t
+MeshPointDevice::GetMtu () const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_mtu;
+}
+
+bool
+MeshPointDevice::IsLinkUp () const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return true;
+}
+
+void
+MeshPointDevice::SetLinkChangeCallback (Callback<void> callback)
+{
+ // do nothing
+}
+
+bool
+MeshPointDevice::IsBroadcast () const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return true;
+}
+
+Address
+MeshPointDevice::GetBroadcast () const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return Mac48Address ("ff:ff:ff:ff:ff:ff");
+}
+
+bool
+MeshPointDevice::IsMulticast () const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return true;
+}
+
+Address
+MeshPointDevice::GetMulticast (Ipv4Address multicastGroup) const
+{
+ NS_LOG_FUNCTION (this << multicastGroup);
+ Mac48Address multicast = Mac48Address::GetMulticast (multicastGroup);
+ return multicast;
+}
+
+bool
+MeshPointDevice::IsPointToPoint () const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return false;
+}
+
+bool
+MeshPointDevice::IsBridge () const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return false;
+}
+
+
+bool
+MeshPointDevice::Send (Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
+{
+ const Mac48Address dst48 = Mac48Address::ConvertFrom (dest);
+ NS_LOG_DEBUG("SEND:, DST = "<<dst48<<", I am: "<<m_address);
+ return m_requestRoute (m_ifIndex, m_address, dst48, packet, protocolNumber, m_myResponse);
+}
+
+bool
+MeshPointDevice::SendFrom (Ptr<Packet> packet, const Address& src, const Address& dest, uint16_t protocolNumber)
+{
+ const Mac48Address src48 = Mac48Address::ConvertFrom (src);
+ const Mac48Address dst48 = Mac48Address::ConvertFrom (dest);
+ return m_requestRoute (m_ifIndex, src48, dst48, packet, protocolNumber, m_myResponse);
+}
+
+Ptr<Node>
+MeshPointDevice::GetNode () const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_node;
+}
+
+void
+MeshPointDevice::SetNode (Ptr<Node> node)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_node = node;
+}
+
+bool
+MeshPointDevice::NeedsArp () const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return true;
+}
+
+void
+MeshPointDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_rxCallback = cb;
+}
+
+void
+MeshPointDevice::SetPromiscReceiveCallback (NetDevice::PromiscReceiveCallback cb)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_promiscRxCallback = cb;
+}
+
+bool
+MeshPointDevice::SupportsSendFrom () const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return true;
+}
+
+Address
+MeshPointDevice::GetMulticast (Ipv6Address addr) const
+{
+ NS_LOG_FUNCTION (this << addr);
+ return Mac48Address::GetMulticast (addr);
+}
+
+//-----------------------------------------------------------------------------
+// Interfaces
+//-----------------------------------------------------------------------------
+uint32_t
+MeshPointDevice::GetNInterfaces () const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_ifaces.size ();
+}
+
+Ptr<NetDevice>
+MeshPointDevice::GetInterface (uint32_t n) const
+{
+ for(std::vector< Ptr<NetDevice> >::const_iterator i = m_ifaces.begin (); i != m_ifaces.end (); i ++)
+ if((*i)->GetIfIndex() == n)
+ return (*i);
+ NS_ASSERT(false);
+ return 0;
+}
+std::vector<Ptr<NetDevice> >
+MeshPointDevice::GetInterfaces () const
+{
+ return m_ifaces;
+}
+void
+MeshPointDevice::AddInterface (Ptr<NetDevice> iface)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+
+ NS_ASSERT (iface != this);
+ if (!Mac48Address::IsMatchingType (iface->GetAddress ()))
+ {
+ NS_FATAL_ERROR ("Device does not support eui 48 addresses: cannot be added to bridge.");
+ }
+ if (!iface->SupportsSendFrom ())
+ {
+ NS_FATAL_ERROR ("Device does not support SendFrom: cannot be added to bridge.");
+ }
+ m_address = Mac48Address::ConvertFrom (iface->GetAddress ());
+
+ NS_LOG_DEBUG ("RegisterProtocolHandler for " << iface->GetInstanceTypeId ().GetName ());
+ m_node->RegisterProtocolHandler (MakeCallback (&MeshPointDevice::ReceiveFromDevice, this),
+ 0, iface, /*promiscuous = */true);
+
+ m_ifaces.push_back (iface);
+ m_channel->AddChannel (iface->GetChannel ());
+}
+
+//-----------------------------------------------------------------------------
+// Protocols
+//-----------------------------------------------------------------------------
+
+void
+MeshPointDevice::SetRoutingProtocol (Ptr<MeshL2RoutingProtocol> protocol)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+
+ NS_ASSERT_MSG (PeekPointer(protocol->GetMeshPoint()) == this, "Routing protocol must be installed on mesh point to be usefull.");
+
+ m_routingProtocol = protocol;
+ m_requestRoute = MakeCallback (&MeshL2RoutingProtocol::RequestRoute, protocol);
+ m_myResponse = MakeCallback (&MeshPointDevice::DoSend, this);
+
+ return;
+}
+
+Ptr<MeshL2RoutingProtocol>
+MeshPointDevice::GetRoutingProtocol () const
+{
+ return m_routingProtocol;
+}
+
+void
+MeshPointDevice::DoSend (bool success, Ptr<Packet> packet, Mac48Address src, Mac48Address dst, uint16_t protocol, uint32_t outIface)
+{
+ if (!success)
+ {
+ NS_LOG_UNCOND ("Resolve failed");
+ return;
+ }
+ // Ok, now I know the route, just SendFrom
+ if (outIface != 0xffffffff)
+ GetInterface (outIface)->SendFrom(packet, src, dst, protocol);
+ else
+ for (std::vector<Ptr<NetDevice> >::iterator i = m_ifaces.begin (); i != m_ifaces.end(); i++)
+ (*i) -> SendFrom (packet, src, dst, protocol);
+}
+
+} // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/mesh-point-device.h Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,175 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ * Pavel Boyko <boyko@iitp.ru>
+ */
+
+
+#ifndef L2ROUTING_NET_DEVICE_H
+#define L2ROUTING_NET_DEVICE_H
+
+#include "ns3/net-device.h"
+#include "ns3/mac48-address.h"
+#include "ns3/bridge-channel.h"
+#include "ns3/mesh-l2-routing-protocol.h"
+
+namespace ns3 {
+
+class Node;
+/**
+ * \ingroup mesh
+ *
+ * \brief Virtual net device modeling mesh point.
+ *
+ * Mesh point is a virtual net device which is responsible for
+ * - Aggreagating and coordinating 1..* real devices -- mesh interfaces, see MeshInterfaceDevice class.
+ * - Hosting all mesh-related level 2 protocols.
+ *
+ * One of hosted L2 protocols must inplement L2RoutingProtocol interface and is used for packets forwarding.
+ *
+ * From the level 3 point of view MeshPointDevice is similar to BridgeNetDevice, but the packets,
+ * which going through may be changed (because L2 protocols may require their own headers or tags).
+ *
+ * Attributes: TODO
+ */
+class MeshPointDevice : public NetDevice
+{
+public:
+ /// Object type ID for NS3 object system
+ static TypeId GetTypeId ();
+ /// C-tor create empty (without interfaces and protocols) mesh point
+ MeshPointDevice ();
+ /// D-tor
+ virtual ~MeshPointDevice ();
+
+ ///\name Interfaces
+ //\{
+ /**
+ * \brief Attach new interface to the station. Interface must support 48-bit MAC address and SendFrom method.
+ *
+ * \attention Only MeshPointDevice can have IP address, but not individual interfaces.
+ */
+ void AddInterface (Ptr<NetDevice> port);
+ /**
+ * \return number of interfaces
+ */
+ uint32_t GetNInterfaces () const;
+ /**
+ * \return interface device by its index (aka ID)
+ * \param id is interface id, 0 <= id < GetNInterfaces
+ */
+ Ptr<NetDevice> GetInterface (uint32_t id) const;
+ /**
+ * \return vector of interfaces
+ */
+ std::vector<Ptr<NetDevice> > GetInterfaces () const;
+ //\}
+
+ ///\name Protocols
+ //\{
+ /// Register routing protocol to be used. Protocol must be alredy installed on this mesh point.
+ void SetRoutingProtocol (Ptr<MeshL2RoutingProtocol> protocol);
+ /// Access current routing protocol
+ Ptr<MeshL2RoutingProtocol> GetRoutingProtocol() const;
+ //\}
+
+ ///\name NetDevice interface for upper layers
+ //\{
+ virtual void SetName (const std::string name);
+ virtual std::string GetName () const;
+ virtual void SetIfIndex (const uint32_t index);
+ virtual uint32_t GetIfIndex () const;
+ virtual Ptr<Channel> GetChannel () const;
+ virtual Address GetAddress () const;
+ virtual bool SetMtu (const uint16_t mtu);
+ virtual uint16_t GetMtu () const;
+ virtual bool IsLinkUp () const;
+ virtual void SetLinkChangeCallback (Callback<void> callback);
+ virtual bool IsBroadcast () const;
+ virtual Address GetBroadcast () const;
+ virtual bool IsMulticast () const;
+ virtual Address GetMulticast (Ipv4Address multicastGroup) const;
+ virtual bool IsPointToPoint () const;
+ virtual bool IsBridge () const;
+ virtual bool Send (Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber);
+ virtual bool SendFrom (Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber);
+ virtual Ptr<Node> GetNode () const;
+ virtual void SetNode (Ptr<Node> node);
+ virtual bool NeedsArp () const;
+ virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb);
+ virtual void SetPromiscReceiveCallback (NetDevice::PromiscReceiveCallback cb);
+ virtual bool SupportsSendFrom () const;
+ virtual Address GetMulticast (Ipv6Address addr) const;
+ virtual void DoDispose ();
+ //\}
+
+private:
+ /// Receive packet from interface
+ void ReceiveFromDevice (Ptr<NetDevice> device, Ptr<const Packet> packet, uint16_t protocol,
+ Address const &source, Address const &destination, PacketType packetType);
+ /// Forward packet down to interfaces
+ void Forward (Ptr<NetDevice> incomingPort, Ptr<Packet> packet,
+ uint16_t protocol, const Mac48Address src, const Mac48Address dst);
+ /**
+ * Response callback for L2 routing protocol. This will be executed when routing information is ready.
+ *
+ * \param success True is route found. TODO: diagnose routing errors
+ * \param packet Packet to send
+ * \param src Source MAC address
+ * \param dst Destination MAC address
+ * \param protocol Protocol ID
+ * \param outIface Interface to use (ID) for send (decided by routing protocol). All interfaces will be used if outIface = 0xffffffff
+ */
+ void DoSend (bool success, Ptr<Packet> packet, Mac48Address src, Mac48Address dst, uint16_t protocol, uint32_t iface);
+
+private:
+ /// Receive action
+ NetDevice::ReceiveCallback m_rxCallback;
+ /// Promisc receive action
+ NetDevice::PromiscReceiveCallback m_promiscRxCallback;
+ /// Mesh point MAC address, supposed to be the address of the first added interface
+ Mac48Address m_address;
+ /// Parent node
+ Ptr<Node> m_node;
+ /// Station name
+ std::string m_name;
+ /// List of interfaces
+ std::vector< Ptr<NetDevice> > m_ifaces;
+ /// If index
+ uint32_t m_ifIndex;
+ /// MTU in bytes
+ uint16_t m_mtu;
+ /// Virtual channel for upper layers
+ Ptr<BridgeChannel> m_channel;
+
+ /// Routing request callback
+ Callback<bool,
+ uint32_t,
+ Mac48Address,
+ Mac48Address,
+ Ptr<Packet>,
+ uint16_t,
+ MeshL2RoutingProtocol::RouteReplyCallback> m_requestRoute;
+
+ /// Routing response callback, this is supplied to mesh routing protocol
+ MeshL2RoutingProtocol::RouteReplyCallback m_myResponse;
+ /// Current routing protocol, used mainly by GetRoutingProtocol
+ Ptr<MeshL2RoutingProtocol> m_routingProtocol;
+};
+} //namespace ns3
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/mesh-wifi-beacon.cc Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,81 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Pavel Boyko <boyko@iitp.ru>
+ */
+
+#include "ns3/mesh-wifi-beacon.h"
+#include <algorithm>
+
+namespace ns3 {
+
+MeshWifiBeacon::MeshWifiBeacon (Ssid ssid, SupportedRates rates, uint64_t us)
+{
+ m_header.SetSsid (ssid);
+ m_header.SetSupportedRates (rates);
+ m_header.SetBeaconIntervalUs (us);
+}
+
+void MeshWifiBeacon::AddInformationElement (Ptr<WifiInformationElement> ie)
+{
+ m_elements.push_back (ie);
+}
+
+namespace {
+/// aux sorter for Ptr<WifiInformationElement>
+struct PIEComparator
+{
+ bool operator () (Ptr<WifiInformationElement> a, Ptr<WifiInformationElement> b) const
+ {
+ return ((*PeekPointer (a)) < (*PeekPointer(b)));
+ }
+};
+}
+
+Ptr<Packet> MeshWifiBeacon::CreatePacket ()
+{
+ Ptr<Packet> packet = Create<Packet> ();
+
+ std::sort (m_elements.begin(), m_elements.end(), PIEComparator());
+
+ std::vector< Ptr<WifiInformationElement> >::const_reverse_iterator i;
+ for (i = m_elements.rbegin(); i != m_elements.rend(); ++i)
+ {
+ packet->AddHeader (**i);
+ }
+
+ packet->AddHeader (BeaconHeader());
+
+ return packet;
+}
+
+WifiMacHeader MeshWifiBeacon::CreateHeader (Mac48Address address)
+{
+ WifiMacHeader hdr;
+
+ hdr.SetBeacon ();
+ hdr.SetAddr1 (Mac48Address::GetBroadcast ());
+ hdr.SetAddr2 (address);
+ hdr.SetAddr3 (Mac48Address ());
+ hdr.SetDsNotFrom ();
+ hdr.SetDsNotTo ();
+
+ return hdr;
+}
+
+} // namespace
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/mesh-wifi-beacon.h Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,71 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Pavel Boyko <boyko@iitp.ru>
+ */
+
+#ifndef MESHWIFIBEACON_H_
+#define MESHWIFIBEACON_H_
+
+#include "ns3/object.h"
+#include "ns3/packet.h"
+#include "ns3/wifi-information-element.h"
+#include "ns3/mgt-headers.h" // from wifi module
+#include "ns3/wifi-mac-header.h"
+
+#include <vector>
+
+namespace ns3 {
+
+/**
+ * \brief Beacon is beacon header + list of arbitrary information elements
+ *
+ * It is supposed that distinct mesh protocols can use beacons to transport
+ * their own information elements.
+ */
+class MeshWifiBeacon
+{
+public:
+ /**
+ * C-tor
+ *
+ * \param ssid is SSID for beacon header
+ * \param rates is a set of supported rates
+ * \param us beacon interval in microseconds
+ */
+ MeshWifiBeacon (Ssid ssid, SupportedRates rates, uint64_t us);
+ /// Read standard Wifi beacon header
+ MgtBeaconHeader BeaconHeader () const { return m_header; }
+ /// Add information element
+ void AddInformationElement (Ptr<WifiInformationElement> ie);
+
+ /// Create wifi header for beacon frame. \param address is sender address
+ WifiMacHeader CreateHeader (Mac48Address address);
+ /// Create frame = { beacon header + all information elements sorted by ElementId () }
+ Ptr<Packet> CreatePacket ();
+
+private:
+ /// Beacon header
+ MgtBeaconHeader m_header;
+ /// List of information elements added
+ std::vector< Ptr<WifiInformationElement> > m_elements;
+};
+
+}
+
+
+#endif /* MESHWIFIBEACON_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/mesh-wifi-interface-mac-plugin.h Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,71 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Pavel Boyko <boyko@iitp.ru>
+ */
+
+#ifndef MESHWIFIINTERFACEMACPLUGIN_H_
+#define MESHWIFIINTERFACEMACPLUGIN_H_
+
+#include "ns3/wifi-mac-header.h"
+#include "ns3/packet.h"
+#include "ns3/mac48-address.h"
+#include "ns3/mesh-wifi-beacon.h"
+#include "ns3/ref-count-base.h"
+
+namespace ns3 {
+
+class MeshWifiInterfaceMac;
+
+/**
+ * \ingroup mesh
+ *
+ * \brief Common interface for mesh point interface MAC plugins
+ *
+ * TODO: plugins description
+ */
+class MeshWifiInterfaceMacPlugin : public RefCountBase
+{
+public:
+ /// This is for subclasses
+ virtual ~MeshWifiInterfaceMacPlugin (){};
+ /// Each plugin must be installed on interface to work
+ virtual void SetParent (Ptr<MeshWifiInterfaceMac> parent) = 0;
+ /**
+ * \brief Process received frame
+ *
+ * \return false if (and only if) frame should be dropped
+ * TODO define when MAC call this
+ */
+ virtual bool Receive (Ptr<Packet> packet, const WifiMacHeader & header) = 0;
+ /**
+ * \brief Update frame before it will be forwarded down
+ *
+ * \return false if (and only if) frame should be dropped
+ * TODO define when MAC call this, preconditions & postconditions
+ */
+ virtual bool UpdateOutcomingFrame (Ptr<Packet> packet, WifiMacHeader & header, Mac48Address from, Mac48Address to) const = 0;
+ /**
+ * \brief Update beacon before it will be formed and sent
+ *
+ * TODO define when MAC call this
+ */
+ virtual void UpdateBeacon (MeshWifiBeacon & beacon) const = 0;
+};
+
+} // namespace ns3
+#endif /* MESHWIFIINTERFACEMACPLUGIN_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/mesh-wifi-interface-mac.cc Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,616 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ * Pavel Boyko <boyko@iitp.ru>
+ */
+
+#include "ns3/mesh-wifi-interface-mac.h"
+#include "ns3/mesh-wifi-beacon.h"
+#include "ns3/log.h"
+#include "ns3/wifi-phy.h"
+#include "ns3/dcf-manager.h"
+#include "ns3/mac-rx-middle.h"
+#include "ns3/mac-low.h"
+#include "ns3/dca-txop.h"
+#include "ns3/random-variable.h"
+#include "ns3/simulator.h"
+#include "ns3/yans-wifi-phy.h"
+
+NS_LOG_COMPONENT_DEFINE ("MeshWifiInterfaceMac");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (MeshWifiInterfaceMac);
+
+TypeId
+MeshWifiInterfaceMac::GetTypeId ()
+{
+ static TypeId tid = TypeId ("ns3::MeshWifiInterfaceMac")
+ .SetParent<WifiMac> ()
+ .AddConstructor<MeshWifiInterfaceMac> ()
+ .AddAttribute ("BeaconInterval", "Beacon Interval",
+ TimeValue (Seconds (1.0)),
+ MakeTimeAccessor (&MeshWifiInterfaceMac::m_beaconInterval),
+ MakeTimeChecker ()
+ )
+ .AddAttribute ("RandomStart", "Window when beacon generating starts (uniform random) in seconds",
+ TimeValue (Seconds (0.1)),
+ MakeTimeAccessor (&MeshWifiInterfaceMac::m_randomStart),
+ MakeTimeChecker ()
+ )
+ .AddAttribute ("BeaconGeneration", "Enable/Disable Beaconing.",
+ BooleanValue (true),
+ MakeBooleanAccessor (
+ &MeshWifiInterfaceMac::SetBeaconGeneration,
+ &MeshWifiInterfaceMac::GetBeaconGeneration
+ ),
+ MakeBooleanChecker ()
+ );
+ return tid;
+}
+
+MeshWifiInterfaceMac::MeshWifiInterfaceMac ()
+{
+ NS_LOG_FUNCTION (this);
+
+ m_rxMiddle = new MacRxMiddle ();
+ m_rxMiddle->SetForwardCallback (MakeCallback (&MeshWifiInterfaceMac::Receive, this));
+
+ m_low = CreateObject<MacLow> ();
+ m_low->SetRxCallback (MakeCallback (&MacRxMiddle::Receive, m_rxMiddle));
+
+ m_dcfManager = new DcfManager ();
+ m_dcfManager->SetupLowListener (m_low);
+
+ m_beaconDca = CreateObject<DcaTxop> ();
+ m_beaconDca->SetLow (m_low);
+ m_beaconDca->SetMinCw (0);
+ m_beaconDca->SetMaxCw (0);
+ m_beaconDca->SetAifsn (1);
+ m_beaconDca->SetManager (m_dcfManager);
+
+ m_VO = CreateObject<DcaTxop> ();
+ m_VO->SetLow (m_low);
+ m_VO->SetMinCw (3);
+ m_VO->SetMaxCw (7);
+ m_VO->SetManager (m_dcfManager);
+
+ m_BE = CreateObject<DcaTxop> ();
+ m_BE->SetLow (m_low);
+ m_BE->SetManager (m_dcfManager);
+}
+
+MeshWifiInterfaceMac::~MeshWifiInterfaceMac ()
+{
+ NS_LOG_FUNCTION (this);
+}
+
+//-----------------------------------------------------------------------------
+// WifiMac inherited
+//-----------------------------------------------------------------------------
+void
+MeshWifiInterfaceMac::SetSlot (Time slotTime)
+{
+ NS_LOG_FUNCTION (this << slotTime);
+ m_dcfManager->SetSlot (slotTime);
+ m_slot = slotTime;
+}
+
+void
+MeshWifiInterfaceMac::SetSifs (Time sifs)
+{
+ NS_LOG_FUNCTION (this << sifs);
+ m_dcfManager->SetSifs (sifs);
+ m_sifs = sifs;
+}
+void
+MeshWifiInterfaceMac::SetAckTimeout (Time ackTimeout)
+{
+ m_low->SetAckTimeout (ackTimeout);
+}
+
+void
+MeshWifiInterfaceMac::SetCtsTimeout (Time ctsTimeout)
+{
+ m_low->SetCtsTimeout (ctsTimeout);
+}
+
+void
+MeshWifiInterfaceMac::SetPifs (Time pifs)
+{
+ NS_LOG_FUNCTION (this << pifs);
+ m_pifs = pifs;
+}
+void
+MeshWifiInterfaceMac::SetEifsNoDifs (Time eifsNoDifs)
+{
+ NS_LOG_FUNCTION (this << eifsNoDifs);
+ m_dcfManager->SetEifsNoDifs (eifsNoDifs);
+ m_eifsNoDifs = eifsNoDifs;
+}
+
+Time
+MeshWifiInterfaceMac::GetSlot () const
+{
+ return m_slot;
+}
+
+Time
+MeshWifiInterfaceMac::GetSifs () const
+{
+ return m_sifs;
+}
+
+Time
+MeshWifiInterfaceMac::GetEifsNoDifs () const
+{
+ return m_eifsNoDifs;
+}
+
+Time
+MeshWifiInterfaceMac::GetAckTimeout () const
+{
+ return m_low->GetAckTimeout ();
+}
+
+Time
+MeshWifiInterfaceMac::GetCtsTimeout () const
+{
+ return m_low->GetCtsTimeout ();
+}
+
+Time
+MeshWifiInterfaceMac::GetPifs () const
+{
+ return m_low->GetPifs ();
+}
+
+void
+MeshWifiInterfaceMac::SetWifiPhy (Ptr<WifiPhy> phy)
+{
+ NS_LOG_FUNCTION (this << phy);
+ m_phy = phy;
+ m_dcfManager->SetupPhyListener (phy);
+ m_low->SetPhy (phy);
+
+ NS_LOG_DEBUG("SetWifiPhy: Can switch channel now: " << CanSwitchChannel() ); // TMP
+}
+
+void
+MeshWifiInterfaceMac::SetWifiRemoteStationManager (Ptr<WifiRemoteStationManager> stationManager)
+{
+ NS_LOG_FUNCTION (this << stationManager);
+ m_stationManager = stationManager;
+ m_BE->SetWifiRemoteStationManager (stationManager);
+ m_VO->SetWifiRemoteStationManager (stationManager);
+ m_beaconDca->SetWifiRemoteStationManager (stationManager);
+ m_low->SetWifiRemoteStationManager (stationManager);
+}
+
+void
+MeshWifiInterfaceMac::Enqueue (Ptr<const Packet> packet, Mac48Address to, Mac48Address from)
+{
+ NS_LOG_FUNCTION (this << packet << to << from);
+ ForwardDown (packet, from, to);
+}
+
+void
+MeshWifiInterfaceMac::Enqueue (Ptr<const Packet> packet, Mac48Address to)
+{
+ NS_LOG_FUNCTION (this << packet << to);
+ ForwardDown (packet, m_low->GetAddress (), to);
+}
+
+bool
+MeshWifiInterfaceMac::SupportsSendFrom () const
+{
+ return true;
+}
+
+void
+MeshWifiInterfaceMac::SetForwardUpCallback (Callback<void,Ptr<Packet>, Mac48Address, Mac48Address> upCallback)
+{
+ NS_LOG_FUNCTION (this);
+ m_upCallback = upCallback;
+}
+
+void
+MeshWifiInterfaceMac::SetLinkUpCallback (Callback<void> linkUp)
+{
+ NS_LOG_FUNCTION (this);
+ if (!linkUp.IsNull ())
+ {
+ linkUp ();
+ }
+}
+
+void
+MeshWifiInterfaceMac::SetLinkDownCallback (Callback<void> linkDown)
+{
+ NS_LOG_FUNCTION (this);
+}
+
+Mac48Address
+MeshWifiInterfaceMac::GetAddress () const
+{
+ return m_address;
+}
+Mac48Address
+MeshWifiInterfaceMac::GetBssid () const
+{
+ return m_address;
+}
+
+Ssid
+MeshWifiInterfaceMac::GetSsid () const
+{
+ return m_meshId;
+}
+
+void
+MeshWifiInterfaceMac::SetAddress (Mac48Address address)
+{
+ NS_LOG_FUNCTION (address);
+ m_low->SetAddress (address);
+ m_address = address;
+}
+
+void
+MeshWifiInterfaceMac::SetSsid (Ssid ssid)
+{
+ NS_LOG_FUNCTION (ssid);
+ m_meshId = ssid;
+}
+
+void
+MeshWifiInterfaceMac::DoDispose ()
+{
+ NS_LOG_FUNCTION (this);
+ delete m_rxMiddle;
+ delete m_dcfManager;
+ //Delete smart pointers:
+ m_rxMiddle = 0;
+ m_low = 0;
+ m_dcfManager = 0;
+ m_phy = 0;
+ m_BE = 0;
+ m_VO = 0;
+ m_beaconSendEvent.Cancel ();
+ m_beaconDca = 0;
+
+ WifiMac::DoDispose ();
+}
+
+//-----------------------------------------------------------------------------
+// Plugins
+//-----------------------------------------------------------------------------
+void
+MeshWifiInterfaceMac::InstallPlugin ( Ptr<MeshWifiInterfaceMacPlugin> plugin)
+{
+ NS_LOG_FUNCTION (this);
+
+ plugin->SetParent (this);
+ m_plugins.push_back (plugin);
+}
+
+//-----------------------------------------------------------------------------
+// Switch channels
+//-----------------------------------------------------------------------------
+bool MeshWifiInterfaceMac::CanSwitchChannel () const
+{
+ NS_LOG_FUNCTION (this);
+
+ // now only YansWifiPhy can switch channels runtime
+ if (m_phy != 0)
+ {
+ Ptr<YansWifiPhy> phy = m_phy->GetObject<YansWifiPhy> ();
+ return (phy != 0);
+ }
+ else
+ return false;
+}
+
+uint16_t MeshWifiInterfaceMac::GetFrequencyChannel () const
+{
+ NS_LOG_FUNCTION (this);
+ NS_ASSERT (m_phy != 0); // need PHY to set/get channel
+
+ Ptr<YansWifiPhy> phy = m_phy->GetObject<YansWifiPhy> ();
+ if (phy != 0)
+ return phy->GetFrequencyChannel ();
+ else
+ return 0;
+}
+
+void MeshWifiInterfaceMac::SwitchFrequencyChannel (uint16_t new_id)
+{
+ NS_LOG_FUNCTION (this);
+ NS_ASSERT (m_phy != 0); // need PHY to set/get channel
+ /* TODO
+ *
+ * Correct channel switching is:
+ *
+ * 1. Interface down, e.g. to stop packets from layer 3
+ * 2. Wait before all output queues will be empty
+ * 3. Switch PHY channel
+ * 4. Interface up
+ *
+ * Now we use dirty channel switch -- just change frequency
+ */
+ NS_ASSERT(CanSwitchChannel());
+
+ Ptr<YansWifiPhy> phy = m_phy->GetObject<YansWifiPhy> ();
+ phy->SetFrequencyChannel (new_id);
+ // Don't know NAV on new channel
+ m_dcfManager->NotifyNavResetNow (Seconds (0));
+}
+
+//-----------------------------------------------------------------------------
+// Forward frame up/down
+//-----------------------------------------------------------------------------
+void
+MeshWifiInterfaceMac::ForwardUp (Ptr<Packet> packet, Mac48Address src, Mac48Address dst)
+{
+ NS_LOG_FUNCTION (this << packet << src);
+ m_upCallback (packet, src, dst);
+}
+
+void
+MeshWifiInterfaceMac::ForwardDown (Ptr<const Packet> const_packet, Mac48Address from, Mac48Address to)
+{
+ // copy packet to allow modifications
+ Ptr<Packet> packet = const_packet->Copy ();
+
+ WifiMacHeader hdr;
+ hdr.SetTypeData ();
+ hdr.SetAddr2 (GetAddress ());
+ hdr.SetAddr3 (to);
+ hdr.SetAddr4 (from);
+ hdr.SetDsFrom ();
+ hdr.SetDsTo ();
+
+ // Address 1 is unknwon here. Routing plugin is responsible to correctly set it.
+ hdr.SetAddr1 (Mac48Address ());
+
+ // Filter packet through all installed plugins
+ for (PluginList::const_iterator i = m_plugins.begin(); i != m_plugins.end(); ++i)
+ {
+ bool drop = ! ((*i)->UpdateOutcomingFrame(packet, hdr, from, to));
+ if (drop) return; // plugin drops frame
+ }
+
+ // Assert that address1 is set. Assert will fail e.g. if there is no installed routing plugin.
+ NS_ASSERT (hdr.GetAddr1() != Mac48Address() );
+
+ // Queue frame
+ WifiRemoteStation *destination = m_stationManager->Lookup (to);
+
+ if (destination->IsBrandNew ())
+ {
+ // in adhoc mode, we assume that every destination
+ // supports all the rates we support.
+ for (uint32_t i = 0; i < m_phy->GetNModes (); i++)
+ {
+ destination->AddSupportedMode (m_phy->GetMode (i));
+ }
+ destination->RecordDisassociated ();
+ }
+ m_BE->Queue (packet, hdr);
+}
+
+void
+MeshWifiInterfaceMac::SendManagementFrame (Ptr<Packet> packet, const WifiMacHeader& hdr)
+{
+ m_VO->Queue (packet, hdr);
+}
+
+SupportedRates
+MeshWifiInterfaceMac::GetSupportedRates () const
+{
+ // set the set of supported rates and make sure that we indicate
+ // the Basic Rate set in this set of supported rates.
+ SupportedRates rates;
+ for (uint32_t i = 0; i < m_phy->GetNModes (); i++)
+ {
+ WifiMode mode = m_phy->GetMode (i);
+ rates.AddSupportedRate (mode.GetDataRate ());
+ }
+ // set the basic rates
+ for (uint32_t j = 0; j < m_stationManager->GetNBasicModes (); j++)
+ {
+ WifiMode mode = m_stationManager->GetBasicMode (j);
+ rates.SetBasicRate (mode.GetDataRate ());
+ }
+ return rates;
+}
+bool
+MeshWifiInterfaceMac::CheckMeshId(Ssid meshId) const
+{
+ return true;
+}
+bool
+MeshWifiInterfaceMac::CheckSupportedRates(SupportedRates rates) const
+{
+ for (uint32_t i = 0; i < m_stationManager->GetNBasicModes (); i++)
+ {
+ WifiMode mode = m_stationManager->GetBasicMode (i);
+ if (!rates.IsSupportedRate (mode.GetDataRate ()))
+ return false;
+ }
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Beacons
+//-----------------------------------------------------------------------------
+void
+MeshWifiInterfaceMac::SetRandomStartDelay (Time interval)
+{
+ NS_LOG_FUNCTION (this << interval);
+ m_randomStart = interval;
+}
+
+void
+MeshWifiInterfaceMac::SetBeaconInterval (Time interval)
+{
+ NS_LOG_FUNCTION (this << interval);
+ m_beaconInterval = interval;
+}
+
+Time
+MeshWifiInterfaceMac::GetBeaconInterval () const
+{
+ return m_beaconInterval;
+}
+
+void
+MeshWifiInterfaceMac::SetBeaconGeneration (bool enable)
+{
+ NS_LOG_FUNCTION (this << enable);
+ if (enable)
+ {
+ // Now start sending beacons after some random delay (to avoid collisions)
+ UniformVariable coefficient (0.0, m_randomStart.GetSeconds());
+ Time randomStart = Seconds (coefficient.GetValue());
+
+ m_beaconSendEvent = Simulator::Schedule (randomStart, &MeshWifiInterfaceMac::SendBeacon, this);
+ m_tbtt = Simulator::Now() + randomStart;
+ }
+ else
+ // stop sending beacons
+ m_beaconSendEvent.Cancel ();
+}
+
+bool
+MeshWifiInterfaceMac::GetBeaconGeneration () const
+{
+ return m_beaconSendEvent.IsRunning ();
+}
+
+Time
+MeshWifiInterfaceMac::GetTbtt () const
+{
+ return m_tbtt;
+}
+
+void MeshWifiInterfaceMac::ShiftTbtt (Time shift)
+{
+ // User of ShiftTbtt () must take care don't shift it to the past
+ NS_ASSERT (GetTbtt() + shift > Simulator::Now());
+
+ m_tbtt += shift;
+ // Shift scheduled event
+ Simulator::Cancel (m_beaconSendEvent);
+ m_beaconSendEvent = Simulator::Schedule (GetTbtt () - Simulator::Now(), &MeshWifiInterfaceMac::SendBeacon, this);
+}
+
+void
+MeshWifiInterfaceMac::ScheduleNextBeacon ()
+{
+ m_tbtt += GetBeaconInterval ();
+ m_beaconSendEvent = Simulator::Schedule (GetBeaconInterval(), &MeshWifiInterfaceMac::SendBeacon, this);
+}
+
+void
+MeshWifiInterfaceMac::SendBeacon ()
+{
+ NS_LOG_FUNCTION (this);
+ NS_LOG_DEBUG (GetAddress() <<" is sending beacon");
+
+ NS_ASSERT (! m_beaconSendEvent.IsRunning());
+ NS_ASSERT (Simulator::Now().GetMicroSeconds() == GetTbtt().GetMicroSeconds()); // assert that beacon is just on time
+
+ // Form & send beacon
+ MeshWifiBeacon beacon (GetSsid (), GetSupportedRates (), m_beaconInterval.GetMicroSeconds ());
+
+ // Ask all plugins to add their specific information elements to beacon
+ for (PluginList::const_iterator i = m_plugins.begin(); i != m_plugins.end(); ++i)
+ (*i)->UpdateBeacon (beacon);
+
+ m_beaconDca->Queue (beacon.CreatePacket(), beacon.CreateHeader(GetAddress()));
+
+ ScheduleNextBeacon ();
+}
+
+void
+MeshWifiInterfaceMac::Receive (Ptr<Packet> packet, WifiMacHeader const *hdr)
+{
+ // Process beacon
+ if((hdr->GetAddr1() != GetAddress()) && (hdr->GetAddr1() != Mac48Address::GetBroadcast()))
+ return;
+ if (hdr->IsBeacon ())
+ {
+ MgtBeaconHeader beacon_hdr;
+ Mac48Address from = hdr->GetAddr2 ();
+
+ packet->PeekHeader (beacon_hdr);
+
+ NS_LOG_DEBUG ("Beacon received from "<<hdr->GetAddr2()<<
+ " I am "<<GetAddress ()<<
+ " at "<<Simulator::Now ().GetMicroSeconds ()<<
+ " microseconds");
+
+ // update supported rates
+ if (beacon_hdr.GetSsid ().IsEqual(GetSsid()))
+ {
+ SupportedRates rates = beacon_hdr.GetSupportedRates ();
+ WifiRemoteStation * peerSta = m_stationManager->Lookup (hdr->GetAddr2 ());
+
+ for (uint32_t i = 0; i < m_phy->GetNModes (); i++)
+ {
+ WifiMode mode = m_phy->GetMode (i);
+ if (rates.IsSupportedRate (mode.GetDataRate ()))
+ {
+ peerSta->AddSupportedMode (mode);
+ if (rates.IsBasicRate (mode.GetDataRate ()))
+ m_stationManager->AddBasicMode (mode);
+ }
+ }
+ }
+ }
+ // Filter frame through all installed plugins
+ for (PluginList::iterator i = m_plugins.begin (); i != m_plugins.end(); ++i)
+ {
+ bool drop = ! ((*i)->Receive(packet, *hdr));
+ if (drop) return; // plugin drops frame
+ }
+
+ // Forward data up
+ if (hdr->IsData ())
+ ForwardUp (packet, hdr->GetAddr4(), hdr->GetAddr3());
+}
+uint32_t
+MeshWifiInterfaceMac::GetLinkMetric (Mac48Address peerAddress)
+{
+ uint32_t metric = 1;
+ if(!m_linkMetricCallback.IsNull ())
+ metric = m_linkMetricCallback(peerAddress, this);
+ return metric;
+}
+void
+MeshWifiInterfaceMac::SetLinkMetricCallback (Callback<uint32_t, Mac48Address, Ptr<MeshWifiInterfaceMac> > cb)
+{
+ m_linkMetricCallback = cb;
+}
+Ptr<WifiRemoteStationManager>
+MeshWifiInterfaceMac::GetStationManager()
+{
+ return m_stationManager;
+}
+} // namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/mesh-wifi-interface-mac.h Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,228 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ * Pavel Boyko <boyko@iitp.ru>
+ */
+
+#ifndef MESHWIFIINTERFACEMAC_H_
+#define MESHWIFIINTERFACEMAC_H_
+
+#include <stdint.h>
+#include <map>
+#include "ns3/mac48-address.h"
+#include "ns3/mgt-headers.h"
+#include "ns3/callback.h"
+#include "ns3/packet.h"
+#include "ns3/nstime.h"
+#include "ns3/wifi-remote-station-manager.h"
+#include "ns3/wifi-mac.h"
+#include "ns3/mesh-wifi-interface-mac-plugin.h"
+#include "ns3/event-id.h"
+
+namespace ns3 {
+
+class WifiMacHeader;
+class DcaTxop;
+class WifiPhy;
+class DcfManager;
+class MacRxMiddle;
+class MacLow;
+/**
+ * \ingroup mesh
+ *
+ * \brief Basic MAC of mesh point Wi-Fi interface. Its function is extendable through plugins mechanism.
+ *
+ * Now only three output queues are used:
+ * - beacons (PIFS and no backoff),
+ * - background traffic,
+ * - management and priority traffic.
+ *
+ */
+class MeshWifiInterfaceMac : public WifiMac
+{
+public:
+ /// Never forget to support typeid
+ static TypeId GetTypeId ();
+ /// C-tor
+ MeshWifiInterfaceMac ();
+ /// D-tor
+ virtual ~MeshWifiInterfaceMac ();
+
+ ///\name Inherited from WifiMac
+ //\{
+ virtual void SetSlot (Time slotTime);
+ virtual void SetSifs (Time sifs);
+ virtual void SetPifs (Time pifs);
+ virtual void SetCtsTimeout (Time ctsTimeout);
+ virtual void SetAckTimeout (Time ackTimeout);
+ virtual void SetEifsNoDifs (Time eifsNoDifs);
+ virtual Time GetSlot () const;
+ virtual Time GetSifs () const;
+ virtual Time GetPifs () const;
+ virtual Time GetCtsTimeout () const;
+ virtual Time GetAckTimeout () const;
+ virtual Time GetEifsNoDifs () const;
+ virtual void SetWifiPhy (Ptr<WifiPhy> phy);
+ virtual void SetWifiRemoteStationManager (Ptr<WifiRemoteStationManager> stationManager);
+ virtual void Enqueue (Ptr<const Packet> packet, Mac48Address to, Mac48Address from);
+ virtual void Enqueue (Ptr<const Packet> packet, Mac48Address to);
+ virtual bool SupportsSendFrom () const;
+ virtual void SetForwardUpCallback (Callback<void,Ptr<Packet>, Mac48Address, Mac48Address> upCallback);
+ virtual void SetLinkUpCallback (Callback<void> linkUp);
+ virtual void SetLinkDownCallback (Callback<void> linkDown);
+ virtual Mac48Address GetAddress () const;
+ virtual Mac48Address GetBssid () const;
+ virtual Ssid GetSsid () const;
+ virtual void SetAddress (Mac48Address address);
+ virtual void SetSsid (Ssid ssid);
+ //\}
+
+ ///\name Beacons
+ //\{
+ /// Set maximum initial random delay before first beacon
+ void SetRandomStartDelay (Time interval);
+ /// Set interval between two successive beacons
+ void SetBeaconInterval (Time interval);
+ /// \return interval between two beacons
+ Time GetBeaconInterval () const;
+ /**
+ * \brief Next beacon frame time
+ *
+ * This is supposed to be used by any entity managing beacon collision avoidance (e.g. Peer management protocol in 802.11s)
+ */
+ Time GetTbtt () const;
+ /**
+ * \brief Shift TBTT.
+ *
+ * This is supposed to be used by any entity managing beacon collision avoidance (e.g. Peer management protocol in 802.11s)
+ *
+ * \attention User of ShiftTbtt () must take care to not shift it to the past.
+ */
+ void ShiftTbtt (Time shift);
+ //\}
+
+ ///\name Plugins
+ //\{
+ /// Install plugin. TODO return unique ID to allow unregister plugins
+ void InstallPlugin (Ptr<MeshWifiInterfaceMacPlugin> plugin);
+ //\}
+
+ /** \name Channel switching
+ *
+ * Channel center frequency = Channel starting frequency + 5 × nch (MHz),
+ * where Starting channel frequency is standard-dependent as defined in IEEE 802.11-2007 17.3.8.3.2.
+ *
+ * Number of channels to use must be limited elsewhere.
+ */
+ //\{
+ /// Return true if PHY layer can switch channels
+ bool CanSwitchChannel () const;
+ /// Current channel Id
+ uint16_t GetFrequencyChannel () const;
+ /// Switch channel
+ void SwitchFrequencyChannel (uint16_t new_id);
+ //\}
+
+ /// To be used by plugins sending management frames.
+ void SendManagementFrame(Ptr<Packet> frame, const WifiMacHeader& hdr);
+ /// \return true if meshId is correct Ssid
+ bool CheckMeshId(Ssid meshId) const;
+ /// \return true if rates are supported
+ bool CheckSupportedRates(SupportedRates rates) const;
+ /// \return list of supported bitrates
+ SupportedRates GetSupportedRates () const;
+ ///\ name Metric Calculation routines:
+ ///\{
+ void SetLinkMetricCallback(Callback<uint32_t, Mac48Address, Ptr<MeshWifiInterfaceMac> > cb);
+ uint32_t GetLinkMetric(Mac48Address peerAddress);
+ Ptr<WifiRemoteStationManager> GetStationManager ();
+ ///\}
+private:
+ /// Frame receive handler
+ void Receive (Ptr<Packet> packet, WifiMacHeader const *hdr);
+ /// Forward frame to mesh point
+ virtual void ForwardUp (Ptr<Packet> packet, Mac48Address src, Mac48Address dst);
+ /// Send frame. Frame is supposed to be tagged by routing information. TODO: clarify this point
+ void ForwardDown (Ptr<const Packet> packet, Mac48Address from, Mac48Address to);
+ /// Send beacon
+ void SendBeacon ();
+ /// Schedule next beacon
+ void ScheduleNextBeacon ();
+ /// Enable/disable beacons
+ void SetBeaconGeneration (bool enable);
+ /// Get current beaconing status
+ bool GetBeaconGeneration () const;
+ /// Real d-tor
+ virtual void DoDispose ();
+
+private:
+ ///\name Wifi MAC internals
+ //\{
+ Ptr<DcaTxop> m_BE;
+ Ptr<DcaTxop> m_BK;
+ Ptr<DcaTxop> m_VI;
+ Ptr<DcaTxop> m_VO;
+ Ptr<DcaTxop> m_beaconDca;
+ Ptr<WifiRemoteStationManager> m_stationManager;
+ Ptr<WifiPhy> m_phy;
+ Callback<void, Ptr<Packet>, Mac48Address, Mac48Address> m_upCallback;
+ //\}
+
+ ///\name Wifi timing intervals
+ //\{
+ Time m_slot;
+ Time m_sifs;
+ Time m_pifs;
+ Time m_ackTimeout;
+ Time m_ctsTimeout;
+ Time m_eifsNoDifs;
+ //\}
+
+ ///\name Mesh timing intervals
+ //\{
+ /// Beaconing interval.
+ Time m_beaconInterval;
+ /// Maximum delay before first beacon
+ Time m_randomStart;
+ /// Time for the next frame
+ Time m_tbtt;
+ //\}
+
+ /// DCF implementation
+ DcfManager* m_dcfManager;
+ /// Middle MAC sublayer
+ MacRxMiddle* m_rxMiddle;
+ /// Low MAC sublayer
+ Ptr<MacLow> m_low;
+ /// My address
+ Mac48Address m_address;
+ /// SSID
+ Ssid m_meshId;
+
+ /// "Timer" for the next beacon
+ EventId m_beaconSendEvent;
+
+ typedef std::vector< Ptr<MeshWifiInterfaceMacPlugin> > PluginList;
+ /// List of all installed plugins
+ PluginList m_plugins;
+ Callback<uint32_t, Mac48Address, Ptr<MeshWifiInterfaceMac> > m_linkMetricCallback;
+};
+
+} // namespace ns3
+
+#endif /* MESHWIFIINTERFACEMAC_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/mesh.h Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,30 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Pavel Boyko <boyko@iitp.ru>
+ *
+ * This is toplevel mesh module description
+ */
+
+/**
+ * \ingroup devices
+ * \defgroup mesh Mesh
+ *
+ * \brief Layer 2 mobile ad hoc wireless (aka mesh) networking
+ *
+ * see http://www.nsnam.org/wiki/index.php/Mesh for module architectural description.
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/waf Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,1 @@
+exec "`dirname "$0"`"/../../../waf "$@"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/wifi-information-element.cc Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,99 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Pavel Boyko <boyko@iitp.ru>
+ */
+
+#include "ns3/wifi-information-element.h"
+#include "ns3/packet.h"
+#include "ns3/log.h"
+
+namespace ns3 {
+
+TypeId
+WifiInformationElement::GetTypeId ()
+{
+ static TypeId tid = TypeId ("ns3::WifiInformationElement")
+ .SetParent<Header> ();
+ return tid;
+}
+
+TypeId
+WifiInformationElement::GetInstanceTypeId () const
+{
+ return GetTypeId ();
+}
+uint32_t WifiInformationElement::GetSerializedSize () const
+{
+ return (GetInformationSize () + 2);
+}
+
+void WifiInformationElement::Serialize (Buffer::Iterator i) const
+{
+ i.WriteU8 (ElementId ());
+ i.WriteU8 (GetInformationSize ());
+ SerializeInformation (i);
+}
+
+uint32_t WifiInformationElement::Deserialize (Buffer::Iterator i)
+{
+ if(i.ReadU8 () != ElementId())
+ return 0;
+ uint8_t length = i.ReadU8 ();
+
+ return (DeserializeInformation (i, length) + 2);
+}
+
+void WifiInformationElement::Print (std::ostream &os) const
+{
+ os << "\n<information_element id=" << ElementId () << ">\n";
+ PrintInformation (os);
+ os << "</information_element>\n";
+}
+
+bool WifiInformationElement::FindFirst(Ptr<Packet> packet)
+{
+ const uint8_t * data = packet->PeekData();
+ uint32_t position = 0;
+ while(position < packet->GetSize ())
+ {
+ if(data[position] == ElementId())
+ {
+ Ptr<Packet> myIe = packet->CreateFragment(position, data[position+1]+2);
+ NS_ASSERT(myIe->GetSize() == (uint32_t)(data[position+1]+2));
+ myIe->RemoveHeader(*this);
+ return true;
+ }
+ else
+ {
+ if(data[position] > ElementId())
+ return false;
+ position +=data[position+1]+2;
+ }
+ }
+ return false;
+}
+
+bool operator< (WifiInformationElement const & a, WifiInformationElement const & b)
+{
+ return (a.ElementId () < b.ElementId());
+}
+
+
+}
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/wifi-information-element.h Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,167 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Pavel Boyko <boyko@iitp.ru>
+ */
+
+#ifndef WIFIINFORMATIONELEMENT_H_
+#define WIFIINFORMATIONELEMENT_H_
+
+#include "ns3/header.h"
+#include "ns3/ref-count-base.h"
+
+namespace ns3 {
+class Packet;
+/**
+ * \ingroup mesh
+ *
+ * \brief Enum of all known information element id (aka tags).
+ *
+ * For now only 802.11s (mesh) related elements are supported here (so 11S prefix),
+ * but this can change in future.
+ *
+ * Note that 802.11s element ids are not yet officially assigned, we use ones
+ * compatible with open80211s (http://o11s.org/) implementation.
+ */
+enum WifiElementId {
+ IE11S_LINK_METRIC_REPORT = 20,
+ IE11S_CONGESTION_NOTIFICATION = 21,
+ IE11S_MESH_CHANNEL_SWITCH_ANNOUNCEMENT= 23,
+ IE11S_MESH_TIM = 24,
+ IE11S_AWAKE_WINDOW = 25,
+ IE11S_SYNCHRONIZATION_PROTOCOL = 26,
+ IE11S_BEACON_TIMING = 27,
+ IE11S_MDAOP_SETUP_REQUEST = 28,
+ IE11S_MDAOP_SETUP_REPLY = 29,
+ IE11S_MDAOP_ADVERTISEMENT = 30,
+ IE11S_MDAOP_SET_TEARDOWN = 31,
+ IE11S_CONNECTIVITY_REPORT = 32,
+ IE11S_PORTAL_ANNOUNCEMENT = 33,
+ IE11S_RANN = 34,
+ IE11S_PROXY_UPDATE = 38,
+ IE11S_PROXY_UPDATE_CONFIRMATION = 39,
+ IE11S_MSCIE = 40,
+ IE11S_MSAIE = 41,
+
+ /* this ID are compatible with open80211s implementation */
+ IE11S_MESH_CONFIGURATION = 51,
+ IE11S_MESH_ID = 52,
+ IE11S_PEER_LINK_MANAGEMENT = 53,
+ /* 54 - 67 */
+ IE11S_PREQ = 68,
+ IE11S_PREP = 69,
+ IE11S_PERR = 70,
+};
+
+/**
+ * \ingroup mesh
+ *
+ * \brief Information element, as defined in 802.11-2007 standard
+ *
+ * Elements are defined to have a common general format consisting of a 1 octet Element ID field, a 1 octet
+ * length field, and a variable-length element-specific information field. Each element is assigned a unique
+ * Element ID as defined in this standard. The Length field specifies the number of octets in the Information
+ * field.
+ */
+class WifiInformationElement : public Header,
+ public RefCountBase // need this to use Ptr<WifiInformationElement>
+{
+public:
+ /// Support object system
+ static TypeId GetTypeId ();
+ TypeId GetInstanceTypeId () const;
+
+ /// virtual d-tor for subclasses
+ virtual ~WifiInformationElement () {}
+
+ ///\name Inherited from Header
+ //\{
+ /**
+ * \return the expected size of the header.
+ *
+ * This method is used by Packet::AddHeader
+ * to store a header into the byte buffer of a packet. This method
+ * should return the number of bytes which are needed to store
+ * the full header data by Serialize.
+ */
+ virtual uint32_t GetSerializedSize () const;
+ /**
+ * \param start an iterator which points to where the header should
+ * be written.
+ *
+ * This method is used by Packet::AddHeader to
+ * store a header into the byte buffer of a packet.
+ * The data written
+ * is expected to match bit-for-bit the representation of this
+ * header in a real network.
+ */
+ virtual void Serialize (Buffer::Iterator start) const;
+ /**
+ * \param start an iterator which points to where the header should
+ * written.
+ * \return the number of bytes read.
+ *
+ * This method is used by Packet::RemoveHeader to
+ * re-create a header from the byte buffer of a packet.
+ * The data read is expected to
+ * match bit-for-bit the representation of this header in real
+ * networks.
+ */
+ virtual uint32_t Deserialize (Buffer::Iterator start);
+ /**
+ * This method is used by Packet::Print to print the
+ * content of a trailer as ascii data to a c++ output stream.
+ * Although the trailer is free to format its output as it
+ * wishes, it is recommended to follow a few rules to integrate
+ * with the packet pretty printer: start with flags, small field
+ * values located between a pair of parens. Values should be separated
+ * by whitespace. Follow the parens with the important fields,
+ * separated by whitespace.
+ * i.e.: (field1 val1 field2 val2 field3 val3) field4 val4 field5 val5
+ */
+ virtual void Print (std::ostream &os) const;
+ /**
+ * This method takes a packet which must be a list of information
+ * elements and looks for an information element of MINE Element ID
+ */
+ bool FindFirst(Ptr<Packet> packet);
+ //\}
+
+protected:
+ ///\name Each subclass must implement
+ //\{
+ /// Own unique Element ID
+ virtual WifiElementId ElementId () const = 0;
+ /// Length of serialized information
+ virtual uint8_t GetInformationSize () const = 0;
+ /// Serialize information
+ virtual void SerializeInformation (Buffer::Iterator start) const = 0;
+ /// Deserialize information
+ virtual uint8_t DeserializeInformation (Buffer::Iterator start, uint8_t length) = 0;
+ /// Print information
+ virtual void PrintInformation (std::ostream &os) const = 0;
+ //\}
+
+ /// Compare information elements using Element ID
+ friend bool operator< (WifiInformationElement const & a, WifiInformationElement const & b);
+};
+
+/// Compare information elements using Element ID
+bool operator< (WifiInformationElement const & a, WifiInformationElement const & b);
+
+} // namespace ns3
+#endif /* WIFIINFORMATIONELEMENT_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/wscript Tue Apr 21 16:22:45 2009 +0400
@@ -0,0 +1,23 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+
+def build(bld):
+ obj = bld.create_ns3_module('mesh', ['wifi', 'dot11s'])
+ obj.source = [
+ 'wifi-information-element.cc',
+ 'mesh-point-device.cc',
+ 'mesh-l2-routing-protocol.cc',
+ 'mesh-wifi-beacon.cc',
+ 'mesh-wifi-interface-mac.cc',
+ ]
+ headers = bld.new_task_gen('ns3header')
+ headers.module = 'mesh'
+ headers.source = [
+ # Refactored
+ 'wifi-information-element.h',
+ 'mesh-point-device.h',
+ 'mesh-l2-routing-protocol.h',
+ 'mesh-wifi-beacon.h',
+ 'mesh-wifi-interface-mac.h',
+ 'mesh-wifi-interface-mac-plugin.h',
+ ]
+
--- a/src/devices/wifi/dca-txop.h Tue Apr 21 12:32:55 2009 +0200
+++ b/src/devices/wifi/dca-txop.h Tue Apr 21 16:22:45 2009 +0400
@@ -161,6 +161,7 @@
bool m_accessOngoing;
Ptr<const Packet> m_currentPacket;
WifiMacHeader m_currentHdr;
+ uint8_t m_currentRetry;
uint8_t m_fragmentNumber;
};
--- a/src/devices/wifi/mac-low.cc Tue Apr 21 12:32:55 2009 +0200
+++ b/src/devices/wifi/mac-low.cc Tue Apr 21 16:22:45 2009 +0400
@@ -537,7 +537,7 @@
{
NS_LOG_DEBUG ("receive cts from="<<m_currentHdr.GetAddr1 ());
SnrTag tag;
- packet->FindFirstMatchingTag (tag);
+ packet->RemovePacketTag (tag);
WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
station->ReportRxOk (rxSnr, txMode);
station->ReportRtsOk (rxSnr, txMode, tag.Get ());
@@ -560,7 +560,7 @@
{
NS_LOG_DEBUG ("receive ack from="<<m_currentHdr.GetAddr1 ());
SnrTag tag;
- packet->FindFirstMatchingTag (tag);
+ packet->RemovePacketTag (tag);
WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
station->ReportRxOk (rxSnr, txMode);
station->ReportDataOk (rxSnr, txMode, tag.Get ());
@@ -1080,7 +1080,7 @@
struct SnrTag tag;
tag.Set (rtsSnr);
- packet->AddTag (tag);
+ packet->AddPacketTag (tag);
ForwardDown (packet, &cts, ctsTxMode);
}
@@ -1159,7 +1159,7 @@
struct SnrTag tag;
tag.Set (dataSnr);
- packet->AddTag (tag);
+ packet->AddPacketTag (tag);
ForwardDown (packet, &ack, ackTxMode);
}
--- a/src/devices/wifi/mgt-headers.cc Tue Apr 21 12:32:55 2009 +0200
+++ b/src/devices/wifi/mgt-headers.cc Tue Apr 21 16:22:45 2009 +0400
@@ -109,6 +109,11 @@
MgtProbeResponseHeader::~MgtProbeResponseHeader ()
{}
+uint64_t
+MgtProbeResponseHeader::GetTimestamp()
+{
+ return m_timestamp;
+}
Ssid
MgtProbeResponseHeader::GetSsid (void) const
{
@@ -198,7 +203,7 @@
MgtProbeResponseHeader::Deserialize (Buffer::Iterator start)
{
Buffer::Iterator i = start;
- i.Next (8); // timestamp
+ m_timestamp = i.ReadNtohU64();
m_beaconInterval = i.ReadNtohU16 ();
m_beaconInterval *= 1024;
i = m_capability.Deserialize (i);
--- a/src/devices/wifi/mgt-headers.h Tue Apr 21 12:32:55 2009 +0200
+++ b/src/devices/wifi/mgt-headers.h Tue Apr 21 16:22:45 2009 +0400
@@ -21,6 +21,7 @@
#define MGT_HEADERS_H
#include <stdint.h>
+//#include <vector>
#include "ns3/header.h"
#include "status-code.h"
@@ -117,6 +118,8 @@
void SetBeaconIntervalUs (uint64_t us);
void SetSupportedRates (SupportedRates rates);
+ uint64_t GetTimestamp();
+
static TypeId GetTypeId (void);
virtual TypeId GetInstanceTypeId (void) const;
virtual void Print (std::ostream &os) const;
@@ -125,6 +128,7 @@
virtual uint32_t Deserialize (Buffer::Iterator start);
private:
+ uint64_t m_timestamp;
Ssid m_ssid;
uint64_t m_beaconInterval;
SupportedRates m_rates;
--- a/src/devices/wifi/wifi-mac-header.cc Tue Apr 21 12:32:55 2009 +0200
+++ b/src/devices/wifi/wifi-mac-header.cc Tue Apr 21 16:22:45 2009 +0400
@@ -125,6 +125,21 @@
m_ctrlType = TYPE_DATA;
m_ctrlSubtype = 0;
}
+
+void
+WifiMacHeader::SetAction (void)
+{
+ m_ctrlType = TYPE_MGT;
+ m_ctrlSubtype = 0x0D;
+}
+
+void
+WifiMacHeader::SetMultihopAction (void)
+{
+ m_ctrlType = TYPE_MGT;
+ m_ctrlSubtype = 0x0F;
+}
+
void
WifiMacHeader::SetType (enum WifiMacType_e type)
{
@@ -188,6 +203,15 @@
case WIFI_MAC_MGT_DEAUTHENTICATION:
m_ctrlType = TYPE_MGT;
m_ctrlSubtype = 12;
+ case WIFI_MAC_MGT_ACTION:
+ m_ctrlType = TYPE_MGT;
+ m_ctrlSubtype = 13;
+ case WIFI_MAC_MGT_ACTION_NO_ACK:
+ m_ctrlType = TYPE_MGT;
+ m_ctrlSubtype = 14;
+ case WIFI_MAC_MGT_MULTIHOP_ACTION:
+ m_ctrlType = TYPE_MGT;
+ m_ctrlSubtype = 15;
break;
case WIFI_MAC_DATA:
@@ -360,6 +384,15 @@
case 12:
return WIFI_MAC_MGT_DEAUTHENTICATION;
break;
+ case 13:
+ return WIFI_MAC_MGT_ACTION;
+ break;
+ case 14:
+ return WIFI_MAC_MGT_ACTION_NO_ACK;
+ break;
+ case 15:
+ return WIFI_MAC_MGT_MULTIHOP_ACTION;
+ break;
}
break;
@@ -553,6 +586,16 @@
{
return (GetType () == WIFI_MAC_MGT_DEAUTHENTICATION)?true:false;
}
+bool
+WifiMacHeader::IsAction (void) const
+{
+ return (GetType () == WIFI_MAC_MGT_ACTION)?true:false;
+}
+bool
+WifiMacHeader::IsMultihopAction (void) const
+{
+ return (GetType () == WIFI_MAC_MGT_MULTIHOP_ACTION)?true:false;
+}
uint16_t
@@ -737,6 +780,9 @@
FOO (MGT_PROBE_RESPONSE);
FOO (MGT_AUTHENTICATION);
FOO (MGT_DEAUTHENTICATION);
+ FOO (MGT_ACTION);
+ FOO (MGT_ACTION_NO_ACK);
+ FOO (MGT_MULTIHOP_ACTION);
FOO (DATA);
FOO (DATA_CFACK);
@@ -821,6 +867,12 @@
<< ", BSSID=" << m_addr3 << ", FragNumber=" << m_seqFrag
<< ", SeqNumber=" << m_seqSeq;
break;
+ case WIFI_MAC_MGT_ACTION:
+ // TODO
+ case WIFI_MAC_MGT_ACTION_NO_ACK:
+ // TODO
+ case WIFI_MAC_MGT_MULTIHOP_ACTION:
+ // TODO
case WIFI_MAC_DATA:
PrintFrameControl (os);
os << " Duration/ID=" << m_duration << "us";
--- a/src/devices/wifi/wifi-mac-header.h Tue Apr 21 12:32:55 2009 +0200
+++ b/src/devices/wifi/wifi-mac-header.h Tue Apr 21 16:22:45 2009 +0400
@@ -44,6 +44,9 @@
WIFI_MAC_MGT_PROBE_RESPONSE,
WIFI_MAC_MGT_AUTHENTICATION,
WIFI_MAC_MGT_DEAUTHENTICATION,
+ WIFI_MAC_MGT_ACTION,
+ WIFI_MAC_MGT_ACTION_NO_ACK,
+ WIFI_MAC_MGT_MULTIHOP_ACTION,
WIFI_MAC_DATA,
WIFI_MAC_DATA_CFACK,
@@ -83,6 +86,8 @@
void SetProbeResp (void);
void SetBeacon (void);
void SetTypeData (void);
+ void SetAction ();
+ void SetMultihopAction();
void SetDsFrom (void);
void SetDsNotFrom (void);
void SetDsTo (void);
@@ -129,6 +134,8 @@
bool IsDisassociation (void) const;
bool IsAuthentication (void) const;
bool IsDeauthentication (void) const;
+ bool IsAction () const;
+ bool IsMultihopAction () const;
uint16_t GetRawDuration (void) const;
Time GetDuration (void) const;
uint16_t GetSequenceControl (void) const;
--- a/src/devices/wifi/wifi-phy-test.cc Tue Apr 21 12:32:55 2009 +0200
+++ b/src/devices/wifi/wifi-phy-test.cc Tue Apr 21 16:22:45 2009 +0400
@@ -167,7 +167,7 @@
CollisionExperiment::SendA (void) const
{
Ptr<Packet> p = Create<Packet> (m_input.packetSizeA);
- p->AddTag (FlowIdTag (m_flowIdA));
+ p->AddByteTag (FlowIdTag (m_flowIdA));
m_txA->SendPacket (p, WifiMode (m_input.txModeA),
WIFI_PREAMBLE_SHORT, m_input.txPowerLevelA);
}
@@ -176,7 +176,7 @@
CollisionExperiment::SendB (void) const
{
Ptr<Packet> p = Create<Packet> (m_input.packetSizeB);
- p->AddTag (FlowIdTag (m_flowIdB));
+ p->AddByteTag (FlowIdTag (m_flowIdB));
m_txB->SendPacket (p, WifiMode (m_input.txModeB),
WIFI_PREAMBLE_SHORT, m_input.txPowerLevelB);
}
@@ -185,7 +185,7 @@
CollisionExperiment::Receive (Ptr<Packet> p, double snr, WifiMode mode, enum WifiPreamble preamble)
{
FlowIdTag tag;
- p->FindFirstMatchingTag (tag);
+ p->FindFirstMatchingByteTag (tag);
if (tag.GetFlowId () == m_flowIdA)
{
m_output.receivedA++;
--- a/src/devices/wifi/wifi-remote-station-manager.cc Tue Apr 21 12:32:55 2009 +0200
+++ b/src/devices/wifi/wifi-remote-station-manager.cc Tue Apr 21 16:22:45 2009 +0400
@@ -433,7 +433,9 @@
WifiRemoteStation::WifiRemoteStation ()
: m_state (BRAND_NEW),
m_ssrc (0),
- m_slrc (0)
+ m_slrc (0),
+ m_avgSlrcCoefficient(0.9),
+ m_avgSlrc (0.0)
{}
WifiRemoteStation::~WifiRemoteStation ()
{}
@@ -557,7 +559,11 @@
{
return GetControlAnswerMode (dataMode);
}
-
+double
+WifiRemoteStation::GetAvgSlrc ()
+{
+ return m_avgSlrc;
+}
uint32_t
WifiRemoteStation::GetNSupportedModes (void) const
{
@@ -577,7 +583,7 @@
return;
}
TxModeTag tag = TxModeTag (DoGetRtsMode (), DoGetDataMode (fullPacketSize));
- packet->AddTag (tag);
+ packet->AddPacketTag (tag);
}
WifiMode
WifiRemoteStation::GetDataMode (Ptr<const Packet> packet, uint32_t fullPacketSize)
@@ -588,7 +594,7 @@
}
TxModeTag tag;
bool found;
- found = packet->FindFirstMatchingTag (tag);
+ found = ConstCast<Packet> (packet)->RemovePacketTag (tag);
NS_ASSERT (found);
return tag.GetDataMode ();
}
@@ -601,7 +607,7 @@
}
TxModeTag tag;
bool found;
- found = packet->FindFirstMatchingTag (tag);
+ found = ConstCast<Packet> (packet)->RemovePacketTag (tag);
NS_ASSERT (found);
return tag.GetRtsMode ();
}
@@ -712,6 +718,7 @@
void
WifiRemoteStation::ReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr)
{
+ m_avgSlrc = m_avgSlrc * m_avgSlrcCoefficient + (double) m_slrc * (1 - m_avgSlrcCoefficient);
m_slrc = 0;
DoReportDataOk (ackSnr, ackMode, dataSnr);
}
--- a/src/devices/wifi/wifi-remote-station-manager.h Tue Apr 21 12:32:55 2009 +0200
+++ b/src/devices/wifi/wifi-remote-station-manager.h Tue Apr 21 16:22:45 2009 +0400
@@ -260,7 +260,7 @@
* handshake.
*/
WifiMode GetAckMode (WifiMode dataMode);
-
+ double GetAvgSlrc ();
private:
virtual Ptr<WifiRemoteStationManager> GetManager (void) const = 0;
virtual WifiMode DoGetDataMode (uint32_t size) = 0;
@@ -289,6 +289,13 @@
SupportedModes m_modes;
TracedValue<uint32_t> m_ssrc;
TracedValue<uint32_t> m_slrc;
+ ///\name needed to calculate average SLRC
+ ///\{
+ ///\brief the coefficient: we valculate averages slrc as
+ //m_avgSlrc = m_avgSlr*coefficient + m_slrc*(1-coefficient);
+ double m_avgSlrcCoefficient;
+ double m_avgSlrc;
+ ///\}
};
} // namespace ns3
--- a/src/devices/wifi/wscript Tue Apr 21 12:32:55 2009 +0200
+++ b/src/devices/wifi/wscript Tue Apr 21 16:22:45 2009 +0400
@@ -58,7 +58,7 @@
'wifi-mode.h',
'ssid.h',
'wifi-preamble.h',
- 'wifi-phy-standard.h',
+ 'wifi-phy-standard.h',
'yans-wifi-phy.h',
'yans-wifi-channel.h',
'wifi-phy.h',
@@ -77,8 +77,17 @@
'nqap-wifi-mac.h',
'wifi-phy.h',
'supported-rates.h',
+ 'mgt-headers.h',
+ 'status-code.h',
+ 'capability-information.h',
'error-rate-model.h',
'yans-error-rate-model.h',
+# Need this for module devices/mesh
+ 'dca-txop.h',
+ 'wifi-mac-header.h',
+ 'dcf-manager.h',
+ 'mac-rx-middle.h',
+ 'mac-low.h',
]
obj = bld.create_ns3_program('wifi-phy-test',
--- a/src/devices/wifi/yans-wifi-channel.cc Tue Apr 21 12:32:55 2009 +0200
+++ b/src/devices/wifi/yans-wifi-channel.cc Tue Apr 21 16:22:45 2009 +0400
@@ -74,13 +74,25 @@
YansWifiChannel::Send (Ptr<YansWifiPhy> sender, Ptr<const Packet> packet, double txPowerDbm,
WifiMode wifiMode, WifiPreamble preamble) const
{
+ NS_LOG_DEBUG ("I am on channel " << sender->GetFrequencyChannel()
+ << " : sending " << packet->GetUid ());
+
Ptr<MobilityModel> senderMobility = sender->GetMobility ()->GetObject<MobilityModel> ();
NS_ASSERT (senderMobility != 0);
uint32_t j = 0;
- for (PhyList::const_iterator i = m_phyList.begin (); i != m_phyList.end (); i++)
- {
+ for (PhyList::const_iterator i = m_phyList.begin (); i != m_phyList.end (); i++, j++)
+ {
if (sender != (*i))
{
+ // For now don't account for interchannel interference
+ if ((*i)->GetFrequencyChannel() != sender->GetFrequencyChannel())
+ {
+ NS_LOG_DEBUG ("Dropped: " << (*i)->GetFrequencyChannel()
+ << " != " << sender->GetFrequencyChannel() );
+ continue;
+ }
+ NS_LOG_DEBUG ("Passed to receiver");
+
Ptr<MobilityModel> receiverMobility = (*i)->GetMobility ()->GetObject<MobilityModel> ();
Time delay = m_delay->GetDelay (senderMobility, receiverMobility);
double rxPowerDbm = m_loss->CalcRxPower (txPowerDbm, senderMobility, receiverMobility);
@@ -90,7 +102,6 @@
Simulator::Schedule (delay, &YansWifiChannel::Receive, this,
j, copy, rxPowerDbm, wifiMode, preamble);
}
- j++;
}
}
--- a/src/devices/wifi/yans-wifi-phy.cc Tue Apr 21 12:32:55 2009 +0200
+++ b/src/devices/wifi/yans-wifi-phy.cc Tue Apr 21 16:22:45 2009 +0400
@@ -115,13 +115,21 @@
PointerValue (),
MakePointerAccessor (&YansWifiPhy::m_state),
MakePointerChecker<WifiPhyStateHelper> ())
+ .AddAttribute ("ChannelSwitchDelay",
+ "Delay between two short frames transmitted on different frequencies",
+ TimeValue (MicroSeconds (250)),
+ MakeTimeAccessor (&YansWifiPhy::m_channelSwitchDelay),
+ MakeTimeChecker ())
+
;
return tid;
}
YansWifiPhy::YansWifiPhy ()
- : m_endSyncEvent (),
- m_random (0.0, 1.0)
+ : m_channelId(0),
+ m_endSyncEvent (),
+ m_random (0.0, 1.0),
+ m_channelStartingFrequency(0.0)
{
NS_LOG_FUNCTION (this);
m_state = CreateObject<WifiPhyStateHelper> ();
@@ -294,6 +302,32 @@
{
m_channel = channel;
m_channel->Add (this);
+ m_channelId = 0; // always start on channel starting frequency
+}
+
+void
+YansWifiPhy::SetFrequencyChannel (uint16_t nch)
+{
+ Simulator::Schedule (m_channelSwitchDelay, &YansWifiPhy::DoSetChannelId, this, nch);
+}
+
+void
+YansWifiPhy::DoSetChannelId (uint16_t nch)
+{
+ NS_LOG_DEBUG("switching channel " << m_channelId << " -> " << nch);
+ m_channelId = nch;
+}
+
+uint16_t
+YansWifiPhy::GetFrequencyChannel() const
+{
+ return m_channelId;
+}
+
+double
+YansWifiPhy::GetChannelCenterFrequency() const
+{
+ return m_channelStartingFrequency + 5e6 * GetFrequencyChannel();
}
void
@@ -430,6 +464,7 @@
{
NS_LOG_FUNCTION (this);
m_interference.Configure80211aParameters ();
+ m_channelStartingFrequency = 5e9; // 5 GHz
m_modes.push_back (WifiPhy::Get6mba ());
m_modes.push_back (WifiPhy::Get9mba ());
m_modes.push_back (WifiPhy::Get12mba ());
--- a/src/devices/wifi/yans-wifi-phy.h Tue Apr 21 12:32:55 2009 +0200
+++ b/src/devices/wifi/yans-wifi-phy.h Tue Apr 21 16:22:45 2009 +0400
@@ -69,6 +69,21 @@
virtual ~YansWifiPhy ();
void SetChannel (Ptr<YansWifiChannel> channel);
+
+ /**
+ * \brief Set channel number.
+ *
+ * Channel center frequency = Channel starting frequency + 5 × nch (MHz)
+ *
+ * where Starting channel frequency is standard-dependent, see SetStandard()
+ * as defined in IEEE 802.11-2007 17.3.8.3.2.
+ */
+ void SetFrequencyChannel (uint16_t id);
+ /// Return current channel ID, see SetChannelId()
+ uint16_t GetFrequencyChannel () const;
+ /// Return current center channel frequency in Hz, see SetChannelId()
+ double GetChannelCenterFrequency() const;
+
void StartReceivePacket (Ptr<Packet> packet,
double rxPowerDbm,
WifiMode mode,
@@ -94,6 +109,8 @@
Ptr<ErrorRateModel> GetErrorRateModel (void) const;
Ptr<Object> GetDevice (void) const;
Ptr<Object> GetMobility (void);
+
+
virtual double GetTxPowerStart (void) const;
@@ -132,6 +149,7 @@
double RatioToDb (double ratio) const;
double GetPowerDbm (uint8_t power) const;
void EndSync (Ptr<Packet> packet, Ptr<InterferenceHelper::Event> event);
+ void DoSetChannelId(uint16_t id);
private:
double m_edThresholdW;
@@ -143,14 +161,18 @@
uint32_t m_nTxPower;
Ptr<YansWifiChannel> m_channel;
+ uint16_t m_channelId;
Ptr<Object> m_device;
Ptr<Object> m_mobility;
Modes m_modes;
EventId m_endSyncEvent;
UniformVariable m_random;
WifiPhyStandard m_standard;
+ /// Standard-dependent center frequency of 0-th channel
+ double m_channelStartingFrequency;
Ptr<WifiPhyStateHelper> m_state;
InterferenceHelper m_interference;
+ Time m_channelSwitchDelay;
};
--- a/src/internet-stack/ipv4-l3-protocol.cc Tue Apr 21 12:32:55 2009 +0200
+++ b/src/internet-stack/ipv4-l3-protocol.cc Tue Apr 21 16:22:45 2009 +0400
@@ -618,7 +618,7 @@
m_identification ++;
SocketSetDontFragmentTag dfTag;
- bool found = packet->FindFirstMatchingTag (dfTag);
+ bool found = packet->RemovePacketTag (dfTag);
if (found)
{
if (dfTag.IsEnabled ())
@@ -635,7 +635,7 @@
// Set TTL to 1 if it is a broadcast packet of any type. Otherwise,
// possibly override the default TTL if the packet is tagged
SocketIpTtlTag tag;
- found = packet->FindFirstMatchingTag (tag);
+ found = packet->RemovePacketTag (tag);
if (destination.IsBroadcast ())
{
@@ -644,7 +644,6 @@
else if (found)
{
ipHeader.SetTtl (tag.GetTtl ());
- // XXX remove tag here?
}
else
{
--- a/src/internet-stack/tcp-socket-impl.cc Tue Apr 21 12:32:55 2009 +0200
+++ b/src/internet-stack/tcp-socket-impl.cc Tue Apr 21 16:22:45 2009 +0400
@@ -544,6 +544,9 @@
m_rxBufSize += i->second->GetSize()-avail;
}
}
+ SocketAddressTag tag;
+ tag.SetAddress (InetSocketAddress (m_remoteAddress, m_remotePort));
+ outPacket->AddPacketTag (tag);
return outPacket;
}
@@ -558,7 +561,7 @@
Ptr<Packet>
TcpSocketImpl::RecvFrom (uint32_t maxSize, uint32_t flags,
- Address &fromAddress)
+ Address &fromAddress)
{
NS_LOG_FUNCTION (this << maxSize << flags);
Ptr<Packet> packet = Recv (maxSize, flags);
@@ -567,7 +570,7 @@
{
SocketAddressTag tag;
bool found;
- found = packet->FindFirstMatchingTag (tag);
+ found = packet->PeekPacketTag (tag);
NS_ASSERT (found);
fromAddress = tag.GetAddress ();
}
@@ -1166,9 +1169,6 @@
p = p->CreateFragment (0,s);
m_nextRxSequence += s; // Advance next expected sequence
NS_LOG_LOGIC("Case 1, advanced nrxs to " << m_nextRxSequence );
- SocketAddressTag tag;
- tag.SetAddress (fromAddress);
- p->AddTag (tag);
//buffer this, it'll be read by call to Recv
UnAckData_t::iterator i =
m_bufferedData.find (tcpHeader.GetSequenceNumber () );
@@ -1236,9 +1236,6 @@
}
}
// Save for later delivery
- SocketAddressTag tag;
- tag.SetAddress (fromAddress);
- p->AddTag (tag);
m_bufferedData[startSeq] = p;
i = m_bufferedData.find (startSeq);
next = i;
@@ -1265,9 +1262,6 @@
p = p->CreateFragment (m_nextRxSequence - tcpHeader.GetSequenceNumber (),s);
SequenceNumber start = m_nextRxSequence;
m_nextRxSequence += s; // Advance next expected sequence
- SocketAddressTag tag;
- tag.SetAddress (fromAddress);
- p->AddTag (tag);
//buffer the new fragment, it'll be read by call to Recv
UnAckData_t::iterator i = m_bufferedData.find (start);
if (i != m_bufferedData.end () ) //we found it already in the buffer
--- a/src/internet-stack/udp-socket-impl.cc Tue Apr 21 12:32:55 2009 +0200
+++ b/src/internet-stack/udp-socket-impl.cc Tue Apr 21 16:22:45 2009 +0400
@@ -324,17 +324,17 @@
{
SocketIpTtlTag tag;
tag.SetTtl (m_ipMulticastTtl);
- p->AddTag (tag);
+ p->AddPacketTag (tag);
}
else if (m_ipTtl != 0 && !dest.IsMulticast () && !dest.IsBroadcast ())
{
SocketIpTtlTag tag;
tag.SetTtl (m_ipTtl);
- p->AddTag (tag);
+ p->AddPacketTag (tag);
}
{
SocketSetDontFragmentTag tag;
- bool found = p->FindFirstMatchingTag (tag);
+ bool found = p->RemovePacketTag (tag);
if (!found)
{
if (m_mtuDiscover)
@@ -345,7 +345,7 @@
{
tag.Disable ();
}
- p->AddTag (tag);
+ p->AddPacketTag (tag);
}
}
//
@@ -464,7 +464,7 @@
Ptr<Packet>
UdpSocketImpl::RecvFrom (uint32_t maxSize, uint32_t flags,
- Address &fromAddress)
+ Address &fromAddress)
{
NS_LOG_FUNCTION (this << maxSize << flags);
Ptr<Packet> packet = Recv (maxSize, flags);
@@ -472,7 +472,7 @@
{
SocketAddressTag tag;
bool found;
- found = packet->FindFirstMatchingTag (tag);
+ found = packet->PeekPacketTag (tag);
NS_ASSERT (found);
fromAddress = tag.GetAddress ();
}
@@ -508,7 +508,7 @@
Address address = InetSocketAddress (ipv4, port);
SocketAddressTag tag;
tag.SetAddress (address);
- packet->AddTag (tag);
+ packet->AddPacketTag (tag);
m_deliveryQueue.push (packet);
m_rxAvailable += packet->GetSize ();
NotifyDataRecv ();
@@ -744,8 +744,8 @@
NS_TEST_ASSERT_EQUAL (m_receivedPacket->GetSize (), 123);
NS_TEST_ASSERT_EQUAL (m_receivedPacket2->GetSize (), 0); // second interface should receive it
- m_receivedPacket->RemoveAllTags ();
- m_receivedPacket2->RemoveAllTags ();
+ m_receivedPacket->RemoveAllPacketTags ();
+ m_receivedPacket2->RemoveAllPacketTags ();
// Simple broadcast test
@@ -758,8 +758,8 @@
// second socket should not receive it (it is bound specifically to the second interface's address
NS_TEST_ASSERT_EQUAL (m_receivedPacket2->GetSize (), 0);
- m_receivedPacket->RemoveAllTags ();
- m_receivedPacket2->RemoveAllTags ();
+ m_receivedPacket->RemoveAllPacketTags ();
+ m_receivedPacket2->RemoveAllPacketTags ();
// Broadcast test with multiple receiving sockets
@@ -779,8 +779,8 @@
NS_TEST_ASSERT_EQUAL (m_receivedPacket->GetSize (), 123);
NS_TEST_ASSERT_EQUAL (m_receivedPacket2->GetSize (), 123);
- m_receivedPacket->RemoveAllTags ();
- m_receivedPacket2->RemoveAllTags ();
+ m_receivedPacket->RemoveAllPacketTags ();
+ m_receivedPacket2->RemoveAllPacketTags ();
Simulator::Destroy ();
--- a/src/node/address.h Tue Apr 21 12:32:55 2009 +0200
+++ b/src/node/address.h Tue Apr 21 16:22:45 2009 +0400
@@ -91,7 +91,7 @@
* can be stored in an Address instance.
*/
enum MaxSize_e {
- MAX_SIZE = 30
+ MAX_SIZE = 20
};
/**
--- a/src/node/packet-socket.cc Tue Apr 21 12:32:55 2009 +0200
+++ b/src/node/packet-socket.cc Tue Apr 21 16:22:45 2009 +0400
@@ -52,7 +52,7 @@
PacketSocket::PacketSocket () : m_rxAvailable (0)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (this);
m_state = STATE_OPEN;
m_shutdownSend = false;
m_shutdownRecv = false;
@@ -64,40 +64,40 @@
void
PacketSocket::SetNode (Ptr<Node> node)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (this << node);
m_node = node;
}
PacketSocket::~PacketSocket ()
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (this);
}
void
PacketSocket::DoDispose (void)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (this);
m_device = 0;
}
enum Socket::SocketErrno
PacketSocket::GetErrno (void) const
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (this);
return m_errno;
}
Ptr<Node>
PacketSocket::GetNode (void) const
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (this);
return m_node;
}
int
PacketSocket::Bind (void)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (this);
PacketSocketAddress address;
address.SetProtocol (0);
address.SetAllDevices ();
@@ -107,7 +107,7 @@
int
PacketSocket::Bind (const Address &address)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (this << address);
if (!PacketSocketAddress::IsMatchingType (address))
{
m_errno = ERROR_INVAL;
@@ -120,7 +120,7 @@
int
PacketSocket::DoBind (const PacketSocketAddress &address)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (this << address);
if (m_state == STATE_BOUND ||
m_state == STATE_CONNECTED)
{
@@ -153,7 +153,7 @@
int
PacketSocket::ShutdownSend (void)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (this);
if (m_state == STATE_CLOSED)
{
m_errno = ERROR_BADF;
@@ -166,7 +166,7 @@
int
PacketSocket::ShutdownRecv (void)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (this);
if (m_state == STATE_CLOSED)
{
m_errno = ERROR_BADF;
@@ -179,7 +179,7 @@
int
PacketSocket::Close(void)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (this);
if (m_state == STATE_CLOSED)
{
m_errno = ERROR_BADF;
@@ -192,7 +192,7 @@
int
PacketSocket::Connect(const Address &ad)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (this << ad);
PacketSocketAddress address;
if (m_state == STATE_CLOSED)
{
@@ -233,7 +233,7 @@
int
PacketSocket::Send (Ptr<Packet> p, uint32_t flags)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (this << p << flags);
if (m_state == STATE_OPEN ||
m_state == STATE_BOUND)
{
@@ -278,7 +278,7 @@
int
PacketSocket::SendTo (Ptr<Packet> p, uint32_t flags, const Address &address)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (this << p << flags << address);
PacketSocketAddress ad;
if (m_state == STATE_CLOSED)
{
@@ -351,7 +351,7 @@
uint16_t protocol, const Address &from,
const Address &to, NetDevice::PacketType packetType)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (this << device << packet << protocol << from << to << packetType);
if (m_shutdownRecv)
{
return;
@@ -365,10 +365,11 @@
if ((m_rxAvailable + packet->GetSize ()) <= m_rcvBufSize)
{
+ Ptr<Packet> copy = packet->Copy ();
SocketAddressTag tag;
tag.SetAddress (address);
- packet->AddTag (tag);
- m_deliveryQueue.push (packet->Copy ());
+ copy->AddPacketTag (tag);
+ m_deliveryQueue.push (copy);
m_rxAvailable += packet->GetSize ();
NS_LOG_LOGIC ("UID is " << packet->GetUid() << " PacketSocket " << this);
NotifyDataRecv ();
@@ -388,7 +389,7 @@
uint32_t
PacketSocket::GetRxAvailable (void) const
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (this);
// We separately maintain this state to avoid walking the queue
// every time this might be called
return m_rxAvailable;
@@ -397,7 +398,7 @@
Ptr<Packet>
PacketSocket::Recv (uint32_t maxSize, uint32_t flags)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (this << maxSize << flags);
if (m_deliveryQueue.empty() )
{
return 0;
@@ -418,13 +419,13 @@
Ptr<Packet>
PacketSocket::RecvFrom (uint32_t maxSize, uint32_t flags, Address &fromAddress)
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (this << maxSize << flags << fromAddress);
Ptr<Packet> packet = Recv (maxSize, flags);
if (packet != 0)
{
SocketAddressTag tag;
bool found;
- found = packet->FindFirstMatchingTag (tag);
+ found = packet->PeekPacketTag (tag);
NS_ASSERT (found);
fromAddress = tag.GetAddress ();
}
@@ -434,7 +435,7 @@
int
PacketSocket::GetSockName (Address &address) const
{
- NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_FUNCTION (this << address);
PacketSocketAddress ad = PacketSocketAddress::ConvertFrom(address);
ad.SetProtocol (m_protocol);
--- a/src/wscript Tue Apr 21 12:32:55 2009 +0200
+++ b/src/wscript Tue Apr 21 16:22:45 2009 +0400
@@ -33,6 +33,8 @@
'helper',
'contrib/stats',
'applications/v4ping',
+ 'devices/mesh',
+ 'devices/mesh/dot11s',
)
def set_options(opt):
--- a/utils/bench-packets.cc Tue Apr 21 12:32:55 2009 +0200
+++ b/utils/bench-packets.cc Tue Apr 21 16:22:45 2009 +0400
@@ -168,14 +168,14 @@
for (uint32_t i = 0; i < n; i++) {
Ptr<Packet> p = Create<Packet> (2000);
- p->AddTag (tag1);
+ p->AddPacketTag (tag1);
p->AddHeader (udp);
- p->FindFirstMatchingTag (tag1);
- p->AddTag (tag2);
+ p->RemovePacketTag (tag1);
+ p->AddPacketTag (tag2);
p->AddHeader (ipv4);
Ptr<Packet> o = p->Copy ();
o->RemoveHeader (ipv4);
- p->FindFirstMatchingTag (tag2);
+ p->RemovePacketTag (tag2);
o->RemoveHeader (udp);
}
}