diff --git a/CHANGES.html b/CHANGES.html
index d7524cf38..c4b2c2800 100644
--- a/CHANGES.html
+++ b/CHANGES.html
@@ -84,6 +84,8 @@ attributes of WifiPhy can now only be used to get the corresponding value
can be now configured through the ChannelSettings attribute. See the wifi model documentation
for information on how to set this new attribute.
UE handover now works with and without enabled CA (carrier aggregation) in inter-eNB, intra-eNB, inter-frequency and intra-frequency scenarios. Previously only inter-eNB intra-frequency handover was supported and only in non-CA scenarios.
+NixVectorRouting: NixVectorRouting can now better cope with topology changes. In-flight packets are not anymore causing crashes, and
+the path is dynamically rebuilt by intermediate routers (this happens only to packets in-flight during the topology change).
diff --git a/src/network/model/nix-vector.cc b/src/network/model/nix-vector.cc
index 586cab50e..cef62cc6d 100644
--- a/src/network/model/nix-vector.cc
+++ b/src/network/model/nix-vector.cc
@@ -33,7 +33,8 @@ NixVector::NixVector ()
: m_nixVector (0),
m_used (0),
m_currentVectorBitSize (0),
- m_totalBitSize (0)
+ m_totalBitSize (0),
+ m_epoch (0)
{
NS_LOG_FUNCTION (this);
@@ -49,7 +50,8 @@ NixVector::NixVector (const NixVector &o)
: m_nixVector (o.m_nixVector),
m_used (o.m_used),
m_currentVectorBitSize (o.m_currentVectorBitSize),
- m_totalBitSize (o.m_totalBitSize)
+ m_totalBitSize (o.m_totalBitSize),
+ m_epoch (o.m_epoch)
{
}
@@ -64,6 +66,7 @@ NixVector::operator = (const NixVector &o)
m_used = o.m_used;
m_currentVectorBitSize = o.m_currentVectorBitSize;
m_totalBitSize = o.m_totalBitSize;
+ m_epoch = o.m_epoch;
return *this;
}
@@ -80,7 +83,8 @@ NixVector::Copy (void) const
/* For printing the nix vector */
std::ostream & operator << (std::ostream &os, const NixVector &nix)
{
- nix.DumpNixVector (os);
+ nix.DumpNixVector (os);
+ os << " (" << nix.GetRemainingBits () << " bits left)";
return os;
}
@@ -111,7 +115,6 @@ NixVector::AddNeighborIndex (uint32_t newBits, uint32_t numberOfBits)
// because we are working with a new
// entry in the vector
m_currentVectorBitSize = numberOfBits;
- m_totalBitSize += numberOfBits;
}
else
{
@@ -133,7 +136,6 @@ NixVector::AddNeighborIndex (uint32_t newBits, uint32_t numberOfBits)
// because we are working with a new
// entry in the vector
m_currentVectorBitSize = (numberOfBits - (32 - m_currentVectorBitSize));
- m_totalBitSize += numberOfBits;
}
}
else
@@ -152,8 +154,8 @@ NixVector::AddNeighborIndex (uint32_t newBits, uint32_t numberOfBits)
// accordingly
m_nixVector.back () = newBits;
m_currentVectorBitSize += numberOfBits;
- m_totalBitSize += numberOfBits;
}
+ m_totalBitSize += numberOfBits;
}
uint32_t
@@ -215,8 +217,11 @@ NixVector::GetSerializedSize (void) const
{
NS_LOG_FUNCTION (this);
uint32_t totalSizeInBytes = 0;
- totalSizeInBytes = sizeof (m_used) + sizeof (m_currentVectorBitSize) +
- sizeof (m_totalBitSize) + (4 * m_nixVector.size ());
+ totalSizeInBytes = sizeof (m_used) +
+ sizeof (m_currentVectorBitSize) +
+ sizeof (m_totalBitSize) +
+ (sizeof (uint32_t) * m_nixVector.size ()) +
+ sizeof (m_epoch);
return totalSizeInBytes;
}
@@ -226,55 +231,20 @@ NixVector::Serialize (uint32_t* buffer, uint32_t maxSize) const
{
NS_LOG_FUNCTION (this << buffer << maxSize);
uint32_t* p = buffer;
- uint32_t size = 0;
- if (size + 4 <= maxSize)
- {
- size += 4;
- // grab number of used bits
- *p++ = m_used;
- }
- else
+ if (maxSize < GetSerializedSize ())
{
return 0;
}
- if (size + 4 <= maxSize)
- {
- size += 4;
- // grab number of current used bits
- // for the front vector
- *p++ = m_currentVectorBitSize;
- }
- else
- {
- return 0;
- }
-
- if (size + 4 <= maxSize)
- {
- size += 4;
- // grab total bit size
- *p++ = m_totalBitSize;
- }
- else
- {
- return 0;
- }
+ *p++ = m_used;
+ *p++ = m_currentVectorBitSize;
+ *p++ = m_totalBitSize;
for (uint32_t j = 0; j < m_nixVector.size (); j++)
{
- if (size + 4 <= maxSize)
- {
- size += 4;
- *p++ = m_nixVector.at (j);
- }
- else
- {
- return 0;
- }
+ *p++ = m_nixVector.at (j);
}
-
- // Serialized successfully
+ *p++ = m_epoch;
return 1;
}
@@ -283,36 +253,42 @@ NixVector::Deserialize (const uint32_t* buffer, uint32_t size)
{
NS_LOG_FUNCTION (this << buffer << size);
const uint32_t* p = buffer;
- uint32_t sizeCheck = size - 4;
- NS_ASSERT (sizeCheck >= 4);
+ NS_ASSERT_MSG (size >= 16, "NixVector minimum serialized length is 16 bytes");
+ if (size < 16)
+ {
+ // return zero if an entire nix-vector was
+ // not deserialized
+ return 0;
+ }
+
m_used = *p++;
- sizeCheck -= 4;
-
- NS_ASSERT (sizeCheck >= 4);
m_currentVectorBitSize = *p++;
- sizeCheck -= 4;
-
- NS_ASSERT (sizeCheck >= 4);
m_totalBitSize = *p++;
- sizeCheck -= 4;
+
+ // NixVector is packed in 32-bit unsigned ints.
+ uint32_t nixVectorLenth = m_totalBitSize / 32 + 1;
+ NS_ASSERT_MSG (size >= 16 + nixVectorLenth,
+ "NixVector serialized length should have been " << 16 + nixVectorLenth << " but buffer is shorter");
+ if (size < 16 + nixVectorLenth * 4)
+ {
+ // return zero if an entire nix-vector was
+ // not deserialized
+ return 0;
+ }
// make sure the nix-vector
// is empty
m_nixVector.clear ();
- while (sizeCheck > 0)
+ for (uint32_t j = 0; j < nixVectorLenth; j++)
{
- NS_ASSERT (sizeCheck >= 4);
uint32_t nix = *p++;
m_nixVector.push_back (nix);
- sizeCheck -= 4;
}
- NS_ASSERT (sizeCheck == 0);
+ m_epoch = *p++;
- // return zero if an entire nix-vector was
- // not deserialized
- return (sizeCheck != 0) ? 0 : 1;
+ return (GetSerializedSize ());
}
void
@@ -353,8 +329,8 @@ NixVector::DumpNixVector (std::ostream &os) const
}
}
-uint32_t
-NixVector::GetRemainingBits (void)
+uint32_t
+NixVector::GetRemainingBits (void) const
{
NS_LOG_FUNCTION (this);
@@ -441,4 +417,16 @@ NixVector::PrintDec2BinNixFill (uint32_t decimalNum, uint32_t bitCount, std::ost
}
}
+void
+NixVector::SetEpoch (uint32_t epoch)
+{
+ m_epoch = epoch;
+}
+
+uint32_t
+NixVector::GetEpoch () const
+{
+ return m_epoch;
+}
+
} // namespace ns3
diff --git a/src/network/model/nix-vector.h b/src/network/model/nix-vector.h
index 86b46524c..73b780635 100644
--- a/src/network/model/nix-vector.h
+++ b/src/network/model/nix-vector.h
@@ -112,7 +112,7 @@ public:
* \return number of bits remaining in the
* nix-vector (ie m_total - m_used)
*/
- uint32_t GetRemainingBits (void);
+ uint32_t GetRemainingBits (void) const;
/**
* \return the number of bytes required for serialization
*/
@@ -150,6 +150,17 @@ public:
*/
uint32_t BitCount (uint32_t numberOfNeighbors) const;
+ /**
+ * Set the NixVector Epoch
+ * \param epoch the NixVector Epoch
+ */
+ void SetEpoch (uint32_t epoch);
+
+ /**
+ * Get the NixVector Epoch
+ * \return the NixVector Epoch
+ */
+ uint32_t GetEpoch () const;
private:
/// Typedef: the NixVector bits storage.
@@ -189,6 +200,8 @@ private:
*/
uint32_t m_totalBitSize;
+ uint32_t m_epoch; //!< Epoch of the Nix-vector creation
+
/**
* Internal for pretty printing of nix-vector (fill)
* \param decimalNum decimal divider
diff --git a/src/network/model/packet.cc b/src/network/model/packet.cc
index 5eeb99593..47aab5df1 100644
--- a/src/network/model/packet.cc
+++ b/src/network/model/packet.cc
@@ -241,7 +241,7 @@ Packet::CreateFragment (uint32_t start, uint32_t length) const
}
void
-Packet::SetNixVector (Ptr nixVector)
+Packet::SetNixVector (Ptr nixVector) const
{
m_nixVector = nixVector;
}
diff --git a/src/network/model/packet.h b/src/network/model/packet.h
index e5387eb5c..5650c29e5 100644
--- a/src/network/model/packet.h
+++ b/src/network/model/packet.h
@@ -687,16 +687,20 @@ public:
/**
* \brief Set the packet nix-vector.
*
- * Note: This function supports a temporary solution
+ * \note Note: This function supports a temporary solution
* to a specific problem in this generic class, i.e.
* how to associate something specific like nix-vector
* with a packet. This design methodology
* should _not_ be followed, and is only here as an
* impetus to fix this general issue.
*
+ * \warning For real this function is not const, as it is the
+ * setter for a mutable variable member. The const qualifier
+ * is needed to set a private mutable variable of const objects.
+ *
* \param nixVector the nix vector
*/
- void SetNixVector (Ptr nixVector);
+ void SetNixVector (Ptr nixVector) const;
/**
* \brief Get the packet nix-vector.
*
@@ -785,7 +789,7 @@ private:
PacketMetadata m_metadata; //!< the packet's metadata
/* Please see comments above about nix-vector */
- Ptr m_nixVector; //!< the packet's Nix vector
+ mutable Ptr m_nixVector; //!< the packet's Nix vector
static uint32_t m_globalUid; //!< Global counter of packets Uid
};
diff --git a/src/nix-vector-routing/doc/nix-vector-routing.rst b/src/nix-vector-routing/doc/nix-vector-routing.rst
index c4c545f60..78bc4dfcb 100644
--- a/src/nix-vector-routing/doc/nix-vector-routing.rst
+++ b/src/nix-vector-routing/doc/nix-vector-routing.rst
@@ -53,6 +53,17 @@ net-devices are added on a node and net-devices added on the channels
associated with current node's net-devices. Please check the ``nix-simple.cc``
example below to understand how nix-vectors are calculated.
+**How does Nix reacts to topology changes?**
+Routes in Nix are specific to a given network topology, and are cached by
+the sender node. Nix monitors the following events: Interface up/down,
+Route add/removal, Address add/removal to understand if the cached routes
+are valid or if they have to be purged.
+
+If the topology changes while the packet is "in flight", the associated
+NixVector is invalid, and have to be rebuilt by an intermediate node.
+This is possible because the NixVecor carries an "Epoch", i.e., a counter
+indicating when the NixVector has been created. If the topology changes,
+the Epoch is globally updated, and any outdated NixVector is rebuilt.
|ns3| supports IPv4 as well as IPv6 Nix-Vector routing.
diff --git a/src/nix-vector-routing/examples/nix-double-wifi.cc b/src/nix-vector-routing/examples/nix-double-wifi.cc
index 73dbe58a6..55a6dcbba 100644
--- a/src/nix-vector-routing/examples/nix-double-wifi.cc
+++ b/src/nix-vector-routing/examples/nix-double-wifi.cc
@@ -65,7 +65,7 @@
* IPv4:
* \verbatim
Time: +7s, Nix Routing
- Route Path: (Node 4 to Node 7, Nix Vector: 100011)
+ Route path from Node 4 to Node 7, Nix Vector: 100011 (6 bits left)
10.1.1.3 (Node 4) ----> 10.1.1.4 (Node 0)
10.1.2.1 (Node 0) ----> 10.1.2.2 (Node 1)
10.1.3.4 (Node 1) ----> 10.1.3.3 (Node 7)
@@ -74,7 +74,7 @@
* IPv6:
* \verbatim
Time: +7s, Nix Routing
- Route Path: (Node 4 to Node 7, Nix Vector: 100011)
+ Route path from Node 4 to Node 7, Nix Vector: 100011 (6 bits left)
2001:1::200:ff:fe00:5 (Node 4) ----> fe80::200:ff:fe00:6 (Node 0)
fe80::200:ff:fe00:1 (Node 0) ----> fe80::200:ff:fe00:2 (Node 1)
fe80::200:ff:fe00:a (Node 1) ----> 2001:3::200:ff:fe00:9 (Node 7)
diff --git a/src/nix-vector-routing/examples/nix-simple-multi-address.cc b/src/nix-vector-routing/examples/nix-simple-multi-address.cc
index 8987a6d4e..4cacfde74 100644
--- a/src/nix-vector-routing/examples/nix-simple-multi-address.cc
+++ b/src/nix-vector-routing/examples/nix-simple-multi-address.cc
@@ -53,7 +53,6 @@
n2 (left) IP: 10.1.2.2
n2 (right) IP: 10.1.3.1, 10.2.3.1
n3 (left) IP: 10.1.3.2, 10.2.3.2
-
\endverbatim
*
* Cases considered:
@@ -63,76 +62,77 @@
* - At t = +3s, Path from n0 to n1 (10.2.1.2).
* - At t = +7s, Path from n0 to n3 (10.2.3.2).
*
+ * Logging output:
* \verbatim
- Logging output:
At time +2s client sent 1024 bytes to 10.1.3.2 port 9
At time +2.01106s server received 1024 bytes from 10.1.1.1 port 49153
At time +2.01106s server sent 1024 bytes to 10.1.1.1 port 49153
At time +2.02212s client received 1024 bytes from 10.1.3.2 port 9
+ \endverbatim
+ *
+ * Output in nix-simple-multi-address.routes:
+ * \verbatim
+ Time: +3s, Nix Routing
+ Route path from Node 0 to Node 1, Nix Vector: 0 (1 bits left)
+ 10.2.1.1 (Node 0) ----> 10.2.1.2 (Node 1)
- Output in nix-simple-multi-address.routes:
- Time: +3s, Nix Routing
- Route Path: (Node 0 to Node 1, Nix Vector: 0)
- 10.2.1.1 (Node 0) ----> 10.2.1.2 (Node 1)
+ Node: 0, Time: +4s, Local time: +4s, Nix Routing
+ NixCache:
+ Destination NixVector
+ 10.1.3.2 011 (3 bits left)
+ IpRouteCache:
+ Destination Gateway Source OutputDevice
+ 10.1.3.2 10.1.1.2 10.1.1.1 1
- Node: 0, Time: +4s, Local time: +4s, Nix Routing
- NixCache:
- Destination NixVector
- 10.1.3.2 011
- 10.2.1.2 0
- Ipv4RouteCache:
- Destination Gateway Source OutputDevice
- 10.1.3.2 10.1.1.2 10.1.1.1 1
+ Node: 1, Time: +4s, Local time: +4s, Nix Routing
+ NixCache:
+ IpRouteCache:
+ Destination Gateway Source OutputDevice
+ 10.1.1.1 10.1.1.1 10.1.1.2 1
+ 10.1.3.2 10.1.2.2 10.1.2.1 2
- Node: 1, Time: +4s, Local time: +4s, Nix Routing
- NixCache:
- Ipv4RouteCache:
- Destination Gateway Source OutputDevice
- 10.1.1.1 10.1.1.1 10.1.1.2 1
- 10.1.3.2 10.1.2.2 10.1.2.1 2
+ Node: 2, Time: +4s, Local time: +4s, Nix Routing
+ NixCache:
+ IpRouteCache:
+ Destination Gateway Source OutputDevice
+ 10.1.1.1 10.1.2.1 10.1.2.2 1
+ 10.1.3.2 10.1.3.2 10.1.3.1 2
- Node: 2, Time: +4s, Local time: +4s, Nix Routing
- NixCache:
- Ipv4RouteCache:
- Destination Gateway Source OutputDevice
- 10.1.1.1 10.1.2.1 10.1.2.2 1
- 10.1.3.2 10.1.3.2 10.1.3.1 2
+ Node: 3, Time: +4s, Local time: +4s, Nix Routing
+ NixCache:
+ Destination NixVector
+ 10.1.1.1 000 (3 bits left)
+ IpRouteCache:
+ Destination Gateway Source OutputDevice
+ 10.1.1.1 10.1.3.1 10.1.3.2 1
- Node: 3, Time: +4s, Local time: +4s, Nix Routing
- NixCache:
- Destination NixVector
- 10.1.1.1 000
- Ipv4RouteCache:
- Destination Gateway Source OutputDevice
- 10.1.1.1 10.1.3.1 10.1.3.2 1
+ Node: 0, Time: +6s, Local time: +6s, Nix Routing
+ NixCache:
+ IpRouteCache:
- Node: 0, Time: +6s, Local time: +6s, Nix Routing
- NixCache:
- Ipv4RouteCache:
+ Node: 1, Time: +6s, Local time: +6s, Nix Routing
+ NixCache:
+ IpRouteCache:
- Node: 1, Time: +6s, Local time: +6s, Nix Routing
- NixCache:
- Ipv4RouteCache:
+ Node: 2, Time: +6s, Local time: +6s, Nix Routing
+ NixCache:
+ IpRouteCache:
- Node: 2, Time: +6s, Local time: +6s, Nix Routing
- NixCache:
- Ipv4RouteCache:
+ Node: 3, Time: +6s, Local time: +6s, Nix Routing
+ NixCache:
+ IpRouteCache:
- Node: 3, Time: +6s, Local time: +6s, Nix Routing
- NixCache:
- Ipv4RouteCache:
-
- Time: +7s, Nix Routing
- Route Path: (Node 0 to Node 3, Nix Vector: 011)
- 10.1.1.1 (Node 0) ----> 10.1.1.2 (Node 1)
- 10.1.2.1 (Node 1) ----> 10.1.2.2 (Node 2)
- 10.1.3.1 (Node 2) ----> 10.2.3.2 (Node 3)
- * \endverbatim
+ Time: +7s, Nix Routing
+ Route path from Node 0 to Node 3, Nix Vector: 011 (3 bits left)
+ 10.1.1.1 (Node 0) ----> 10.1.1.2 (Node 1)
+ 10.1.2.1 (Node 1) ----> 10.1.2.2 (Node 2)
+ 10.1.3.1 (Node 2) ----> 10.2.3.2 (Node 3)
+ \endverbatim
*/
using namespace ns3;
-NS_LOG_COMPONENT_DEFINE ("NixSimpleExample");
+NS_LOG_COMPONENT_DEFINE ("NixSimpleMultiAddressExample");
int
main (int argc, char *argv[])
diff --git a/src/nix-vector-routing/examples/nix-simple.cc b/src/nix-vector-routing/examples/nix-simple.cc
index 12ba2435b..9dca2bbcf 100644
--- a/src/nix-vector-routing/examples/nix-simple.cc
+++ b/src/nix-vector-routing/examples/nix-simple.cc
@@ -78,114 +78,104 @@
* - Source (n1) and Destination (n1)
* It goes from n1 -> n1
* .
+ *
+ * Expected IPv4 Routing Path output for above
+ * cases (in the output stream):
* \verbatim
- Expected IPv4 Routing Path output for above
- cases (in the output stream):
- Time: +3s, Nix Routing
- Route Path: (Node 0 to Node 3, Nix Vector: 101)
- 10.1.4.1 (Node 0) ----> 10.1.4.2 (Node 2)
- 10.1.3.1 (Node 2) ----> 10.1.3.2 (Node 3)
+ Time: +3s, Nix Routing
+ Route path from Node 0 to Node 3, Nix Vector: 101 (3 bits left)
+ 10.1.4.1 (Node 0) ----> 10.1.4.2 (Node 2)
+ 10.1.3.1 (Node 2) ----> 10.1.3.2 (Node 3)
- Time: +5s, Nix Routing
- Route Path: (Node 1 to Node 3, Nix Vector: 101)
- 10.1.2.1 (Node 1) ----> 10.1.2.2 (Node 2)
- 10.1.3.1 (Node 2) ----> 10.1.3.2 (Node 3)
+ Time: +5s, Nix Routing
+ Route path from Node 1 to Node 3, Nix Vector: 101 (3 bits left)
+ 10.1.2.1 (Node 1) ----> 10.1.2.2 (Node 2)
+ 10.1.3.1 (Node 2) ----> 10.1.3.2 (Node 3)
- Time: +6s, Nix Routing
- Route Path: (Node 2 to Node 0, Nix Vector: 10)
- 10.1.4.2 (Node 2) ----> 10.1.4.1 (Node 0)
+ Time: +6s, Nix Routing
+ Route path from Node 2 to Node 0, Nix Vector: 10 (2 bits left)
+ 10.1.4.2 (Node 2) ----> 10.1.1.1 (Node 0)
- Time: +7s, Nix Routing
- Route Path: (Node 1 to Node 1, Nix Vector: )
- 10.1.1.2 (Node 1) ----> 10.1.1.2 (Node 1)
+ Time: +7s, Nix Routing
+ Route path from Node 1 to Node 1, Nix Vector:
+ 10.1.1.2 (Node 1) ----> 10.1.1.2 (Node 1)
- Node: 0, Time: +8s, Local time: +8s, Nix Routing
- NixCache:
- Destination NixVector
- 10.1.3.2 101
- Ipv4RouteCache:
- Destination Gateway Source OutputDevice
- 10.1.3.2 10.1.4.2 10.1.4.1 2
+ Node: 0, Time: +8s, Local time: +8s, Nix Routing
+ NixCache:
+ Destination NixVector
+ 10.1.3.2 101 (3 bits left)
+ IpRouteCache:
+ Destination Gateway Source OutputDevice
+ 10.1.3.2 10.1.4.2 10.1.4.1 1
- Node: 1, Time: +8s, Local time: +8s, Nix Routing
- NixCache:
- Destination NixVector
- 10.1.3.2 101
- Ipv4RouteCache:
- Destination Gateway Source OutputDevice
- 10.1.3.2 10.1.2.2 10.1.2.1 2
+ Node: 1, Time: +8s, Local time: +8s, Nix Routing
+ NixCache:
+ IpRouteCache:
- Node: 2, Time: +8s, Local time: +8s, Nix Routing
- NixCache:
- Destination NixVector
- 10.1.1.1 10
- Ipv4RouteCache:
- Destination Gateway Source OutputDevice
- 10.1.1.1 10.1.4.1 10.1.4.2 3
- 10.1.3.2 10.1.3.2 10.1.3.1 2
- 10.1.4.1 10.1.4.1 10.1.4.2 3
+ Node: 2, Time: +8s, Local time: +8s, Nix Routing
+ NixCache:
+ IpRouteCache:
+ Destination Gateway Source OutputDevice
+ 10.1.3.2 10.1.3.2 10.1.3.1 1
+ 10.1.4.1 10.1.4.1 10.1.4.2 2
- Node: 3, Time: +8s, Local time: +8s, Nix Routing
- NixCache:
- Destination NixVector
- 10.1.4.1 010
- Ipv4RouteCache:
- Destination Gateway Source OutputDevice
- 10.1.4.1 10.1.3.1 10.1.3.2 1
+ Node: 3, Time: +8s, Local time: +8s, Nix Routing
+ NixCache:
+ Destination NixVector
+ 10.1.4.1 010 (3 bits left)
+ IpRouteCache:
+ Destination Gateway Source OutputDevice
+ 10.1.4.1 10.1.3.1 10.1.3.2 0
\endverbatim
*
+ * Expected IPv6 Routing Path output for above
+ * cases (in the output stream):
* \verbatim
- Expected IPv6 Routing Path output for above
- cases (in the output stream):
- Time: +3s, Nix Routing
- Route Path: (Node 0 to Node 3, Nix Vector: 101)
- 2001:4::200:ff:fe00:7 (Node 0) ----> fe80::200:ff:fe00:8 (Node 2)
- fe80::200:ff:fe00:5 (Node 2) ----> 2001:3::200:ff:fe00:6 (Node 3)
+ Time: +3s, Nix Routing
+ Route path from Node 0 to Node 3, Nix Vector: 101 (3 bits left)
+ 2001:4::200:ff:fe00:7 (Node 0) ----> fe80::200:ff:fe00:8 (Node 2)
+ fe80::200:ff:fe00:5 (Node 2) ----> 2001:3::200:ff:fe00:6 (Node 3)
- Time: +5s, Nix Routing
- Route Path: (Node 1 to Node 3, Nix Vector: 101)
- 2001:2::200:ff:fe00:3 (Node 1) ----> fe80::200:ff:fe00:4 (Node 2)
- fe80::200:ff:fe00:5 (Node 2) ----> 2001:3::200:ff:fe00:6 (Node 3)
+ Time: +5s, Nix Routing
+ Route path from Node 1 to Node 3, Nix Vector: 101 (3 bits left)
+ 2001:2::200:ff:fe00:3 (Node 1) ----> fe80::200:ff:fe00:4 (Node 2)
+ fe80::200:ff:fe00:5 (Node 2) ----> 2001:3::200:ff:fe00:6 (Node 3)
- Time: +6s, Nix Routing
- Route Path: (Node 2 to Node 0, Nix Vector: 10)
- 2001:4::200:ff:fe00:8 (Node 2) ----> 2001:1::200:ff:fe00:1 (Node 0)
+ Time: +6s, Nix Routing
+ Route path from Node 2 to Node 0, Nix Vector: 10 (2 bits left)
+ 2001:4::200:ff:fe00:8 (Node 2) ----> 2001:1::200:ff:fe00:1 (Node 0)
- Time: +7s, Nix Routing
- Route Path: (Node 1 to Node 1, Nix Vector: )
- 2001:1::200:ff:fe00:2 (Node 1) ----> 2001:1::200:ff:fe00:2 (Node 1)
+ Time: +7s, Nix Routing
+ Route path from Node 1 to Node 1, Nix Vector:
+ 2001:1::200:ff:fe00:2 (Node 1) ----> 2001:1::200:ff:fe00:2 (Node 1)
- Node: 0, Time: +8s, Local time: +8s, Nix Routing
- NixCache:
- Destination NixVector
- 2001:3::200:ff:fe00:6 101
- IpRouteCache:
- Destination Gateway Source OutputDevice
- 2001:3::200:ff:fe00:6 fe80::200:ff:fe00:8 2001:4::200:ff:fe00:7 1
+ Node: 0, Time: +8s, Local time: +8s, Nix Routing
+ NixCache:
+ Destination NixVector
+ 2001:3::200:ff:fe00:6 101 (3 bits left)
+ IpRouteCache:
+ Destination Gateway Source OutputDevice
+ 2001:3::200:ff:fe00:6 fe80::200:ff:fe00:8 2001:4::200:ff:fe00:7 1
- Node: 1, Time: +8s, Local time: +8s, Nix Routing
- NixCache:
- Destination NixVector
- 2001:3::200:ff:fe00:6 101
- IpRouteCache:
+ Node: 1, Time: +8s, Local time: +8s, Nix Routing
+ NixCache:
+ IpRouteCache:
- Node: 2, Time: +8s, Local time: +8s, Nix Routing
- NixCache:
- Destination NixVector
- 2001:1::200:ff:fe00:1 10
- IpRouteCache:
- Destination Gateway Source OutputDevice
- 2001:3::200:ff:fe00:6 fe80::200:ff:fe00:6 fe80::200:ff:fe00:5 1
- 2001:4::200:ff:fe00:7 fe80::200:ff:fe00:7 fe80::200:ff:fe00:8 2
+ Node: 2, Time: +8s, Local time: +8s, Nix Routing
+ NixCache:
+ IpRouteCache:
+ Destination Gateway Source OutputDevice
+ 2001:3::200:ff:fe00:6 fe80::200:ff:fe00:6 fe80::200:ff:fe00:5 1
+ 2001:4::200:ff:fe00:7 fe80::200:ff:fe00:7 fe80::200:ff:fe00:8 2
- Node: 3, Time: +8s, Local time: +8s, Nix Routing
- NixCache:
- Destination NixVector
- 2001:4::200:ff:fe00:7 010
- IpRouteCache:
- Destination Gateway Source OutputDevice
- 2001:4::200:ff:fe00:7 fe80::200:ff:fe00:5 2001:3::200:ff:fe00:6 0
- \endverbatim
+ Node: 3, Time: +8s, Local time: +8s, Nix Routing
+ NixCache:
+ Destination NixVector
+ 2001:4::200:ff:fe00:7 010 (3 bits left)
+ IpRouteCache:
+ Destination Gateway Source OutputDevice
+ 2001:4::200:ff:fe00:7 fe80::200:ff:fe00:5 2001:3::200:ff:fe00:6 0
+ \endverbatim
*/
using namespace ns3;
@@ -204,35 +194,21 @@ main (int argc, char *argv[])
LogComponentEnable ("UdpEchoClientApplication", LOG_LEVEL_INFO);
LogComponentEnable ("UdpEchoServerApplication", LOG_LEVEL_INFO);
- NodeContainer nodes12;
- nodes12.Create (2);
-
- NodeContainer nodes23;
- nodes23.Add (nodes12.Get (1));
- nodes23.Create (1);
-
- NodeContainer nodes34;
- nodes34.Add (nodes23.Get (1));
- nodes34.Create (1);
-
- NodeContainer nodes13;
- nodes13.Add (nodes12.Get (0));
- nodes13.Add (nodes34.Get (0));
+ NodeContainer nodes;
+ nodes.Create (4);
PointToPointHelper pointToPoint;
pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
- NodeContainer allNodes = NodeContainer (nodes12, nodes23.Get (1), nodes34.Get (1));
-
+ NetDeviceContainer devices01;
NetDeviceContainer devices12;
NetDeviceContainer devices23;
- NetDeviceContainer devices34;
- NetDeviceContainer devices13;
- devices12 = pointToPoint.Install (nodes12);
- devices23 = pointToPoint.Install (nodes23);
- devices34 = pointToPoint.Install (nodes34);
- devices13 = pointToPoint.Install (nodes13);
+ NetDeviceContainer devices02;
+ devices01 = pointToPoint.Install (NodeContainer (nodes.Get (0), nodes.Get (1)));
+ devices12 = pointToPoint.Install (NodeContainer (nodes.Get (1), nodes.Get (2)));
+ devices23 = pointToPoint.Install (NodeContainer (nodes.Get (2), nodes.Get (3)));
+ devices02 = pointToPoint.Install (NodeContainer (nodes.Get (0), nodes.Get (2)));
Address udpServerAddress;
@@ -243,7 +219,7 @@ main (int argc, char *argv[])
Ipv4NixVectorHelper nixRouting;
InternetStackHelper stack;
stack.SetRoutingHelper (nixRouting); // has effect on the next Install ()
- stack.Install (allNodes);
+ stack.Install (nodes);
Ipv4AddressHelper address1;
address1.SetBase ("10.1.1.0", "255.255.255.0");
@@ -254,19 +230,19 @@ main (int argc, char *argv[])
Ipv4AddressHelper address4;
address4.SetBase ("10.1.4.0", "255.255.255.0");
- Ipv4InterfaceContainer interfaces12 = address1.Assign (devices12);
- Ipv4InterfaceContainer interfaces23 = address2.Assign (devices23);
- Ipv4InterfaceContainer interfaces34 = address3.Assign (devices34);
- Ipv4InterfaceContainer interfaces13 = address4.Assign (devices13);
+ Ipv4InterfaceContainer interfaces01 = address1.Assign (devices01);
+ Ipv4InterfaceContainer interfaces12 = address2.Assign (devices12);
+ Ipv4InterfaceContainer interfaces23 = address3.Assign (devices23);
+ Ipv4InterfaceContainer interfaces02 = address4.Assign (devices02);
- udpServerAddress = interfaces34.GetAddress (1);
+ udpServerAddress = interfaces23.GetAddress (1);
// Trace routing paths for different source and destinations.
Ptr routingStream = Create ("nix-simple-ipv4.routes", std::ios::out);
- nixRouting.PrintRoutingPathAt (Seconds (3), nodes12.Get (0), interfaces34.GetAddress (1), routingStream);
- nixRouting.PrintRoutingPathAt (Seconds (5), nodes12.Get (1), interfaces34.GetAddress (1), routingStream);
- nixRouting.PrintRoutingPathAt (Seconds (6), nodes23.Get (1), interfaces12.GetAddress (0), routingStream);
- nixRouting.PrintRoutingPathAt (Seconds (7), nodes12.Get (1), interfaces12.GetAddress (1), routingStream);
+ nixRouting.PrintRoutingPathAt (Seconds (3), nodes.Get (0), interfaces23.GetAddress (1), routingStream);
+ nixRouting.PrintRoutingPathAt (Seconds (5), nodes.Get (1), interfaces23.GetAddress (1), routingStream);
+ nixRouting.PrintRoutingPathAt (Seconds (6), nodes.Get (2), interfaces01.GetAddress (0), routingStream);
+ nixRouting.PrintRoutingPathAt (Seconds (7), nodes.Get (1), interfaces01.GetAddress (1), routingStream);
// Trace routing tables
nixRouting.PrintRoutingTableAllAt (Seconds (8), routingStream);
}
@@ -277,7 +253,7 @@ main (int argc, char *argv[])
Ipv6NixVectorHelper nixRouting;
InternetStackHelper stack;
stack.SetRoutingHelper (nixRouting); // has effect on the next Install ()
- stack.Install (allNodes);
+ stack.Install (nodes);
Ipv6AddressHelper address1;
address1.SetBase (Ipv6Address ("2001:1::"), Ipv6Prefix (64));
@@ -288,26 +264,26 @@ main (int argc, char *argv[])
Ipv6AddressHelper address4;
address4.SetBase (Ipv6Address ("2001:4::"), Ipv6Prefix (64));
- Ipv6InterfaceContainer interfaces12 = address1.Assign (devices12);
- Ipv6InterfaceContainer interfaces23 = address2.Assign (devices23);
- Ipv6InterfaceContainer interfaces34 = address3.Assign (devices34);
- Ipv6InterfaceContainer interfaces13 = address4.Assign (devices13);
+ Ipv6InterfaceContainer interfaces01 = address1.Assign (devices01);
+ Ipv6InterfaceContainer interfaces12 = address2.Assign (devices12);
+ Ipv6InterfaceContainer interfaces23 = address3.Assign (devices23);
+ Ipv6InterfaceContainer interfaces02 = address4.Assign (devices02);
- udpServerAddress = interfaces34.GetAddress (1, 1);
+ udpServerAddress = interfaces23.GetAddress (1, 1);
// Trace routing paths for different source and destinations.
Ptr routingStream = Create ("nix-simple-ipv6.routes", std::ios::out);
- nixRouting.PrintRoutingPathAt (Seconds (3), nodes12.Get (0), interfaces34.GetAddress (1, 1), routingStream);
- nixRouting.PrintRoutingPathAt (Seconds (5), nodes12.Get (1), interfaces34.GetAddress (1, 1), routingStream);
- nixRouting.PrintRoutingPathAt (Seconds (6), nodes23.Get (1), interfaces12.GetAddress (0, 1), routingStream);
- nixRouting.PrintRoutingPathAt (Seconds (7), nodes12.Get (1), interfaces12.GetAddress (1, 1), routingStream);
+ nixRouting.PrintRoutingPathAt (Seconds (3), nodes.Get (0), interfaces23.GetAddress (1, 1), routingStream);
+ nixRouting.PrintRoutingPathAt (Seconds (5), nodes.Get (1), interfaces23.GetAddress (1, 1), routingStream);
+ nixRouting.PrintRoutingPathAt (Seconds (6), nodes.Get (2), interfaces01.GetAddress (0, 1), routingStream);
+ nixRouting.PrintRoutingPathAt (Seconds (7), nodes.Get (1), interfaces01.GetAddress (1, 1), routingStream);
// Trace routing tables
nixRouting.PrintRoutingTableAllAt (Seconds (8), routingStream);
}
UdpEchoServerHelper echoServer (9);
- ApplicationContainer serverApps = echoServer.Install (nodes34.Get (1));
+ ApplicationContainer serverApps = echoServer.Install (nodes.Get (3));
serverApps.Start (Seconds (1.0));
serverApps.Stop (Seconds (10.0));
@@ -316,7 +292,7 @@ main (int argc, char *argv[])
echoClient.SetAttribute ("Interval", TimeValue (Seconds (1.)));
echoClient.SetAttribute ("PacketSize", UintegerValue (1024));
- ApplicationContainer clientApps = echoClient.Install (nodes12.Get (0));
+ ApplicationContainer clientApps = echoClient.Install (nodes.Get (0));
clientApps.Start (Seconds (2.0));
clientApps.Stop (Seconds (10.0));
diff --git a/src/nix-vector-routing/model/nix-vector-routing.cc b/src/nix-vector-routing/model/nix-vector-routing.cc
index 3504a7670..cbdec1757 100644
--- a/src/nix-vector-routing/model/nix-vector-routing.cc
+++ b/src/nix-vector-routing/model/nix-vector-routing.cc
@@ -44,6 +44,9 @@ NS_OBJECT_TEMPLATE_CLASS_DEFINE (NixVectorRouting, Ipv6RoutingProtocol);
template
bool NixVectorRouting::g_isCacheDirty = false;
+template
+uint32_t NixVectorRouting::g_epoch = 0;
+
template
typename NixVectorRouting::IpAddressToNodeMap NixVectorRouting::g_ipAddressToNodeMap;
@@ -183,6 +186,7 @@ NixVectorRouting::GetNixVector (Ptr source, IpAddress dest, Ptr nixVector = Create ();
+ nixVector->SetEpoch (g_epoch);
// not in cache, must build the nix vector
// First, we have to figure out the nodes
@@ -724,9 +728,11 @@ NixVectorRouting::RouteOutput (Ptr p, const IpHeader &header, Ptr::RouteInput (Ptr p, const IpHeader &header, Pt
if (!lcb.IsNull ())
{
NS_LOG_LOGIC ("Local delivery to " << destAddress);
+ p->SetNixVector (nullptr);
lcb (p, header, iif);
return true;
}
@@ -894,6 +901,14 @@ NixVectorRouting::RouteInput (Ptr p, const IpHeader &header, Pt
// If nixVector isn't in packet, something went wrong
NS_ASSERT (nixVector);
+ if (nixVector->GetEpoch () != g_epoch)
+ {
+ NS_LOG_LOGIC ("NixVector epoch mismatch (" << nixVector->GetEpoch () << " Vs " << g_epoch
+ << ") - rebuilding it");
+ nixVector = GetNixVector (m_node, destAddress, 0);
+ p->SetNixVector (nixVector);
+ }
+
// Get the interface number that we go out of, by extracting
// from the nix-vector
if (m_totalNeighbors == 0)
@@ -978,9 +993,14 @@ NixVectorRouting::PrintRoutingTable (Ptr stream, Time::U
{
*os << *(it->second) << std::endl;
}
+ else
+ {
+ *os << "-" << std::endl;
+ }
}
}
- *os << "IpRouteCache:" << std::endl;
+
+ *os << "IpRouteCache:" << std::endl;
if (m_ipRouteCache.size () > 0)
{
*os << std::setw (30) << "Destination";
@@ -1238,8 +1258,8 @@ NixVectorRouting::PrintRoutingPath (Ptr source, IpAddress dest,
*os << std::resetiosflags (std::ios::adjustfield) << std::setiosflags (std::ios::left);
*os << "Time: " << Now().As (unit)
<< ", Nix Routing" << std::endl;
- *os << "Route Path: ";
- *os << "(Node " << source->GetId () << " to Node " << destNode->GetId () << ", ";
+ *os << "Route path from ";
+ *os << "Node " << source->GetId () << " to Node " << destNode->GetId () << ", ";
*os << "Nix Vector: ";
// Check the Nix cache
@@ -1253,8 +1273,6 @@ NixVectorRouting::PrintRoutingPath (Ptr source, IpAddress dest,
// Build the nix-vector, given the source node and the
// dest IP address
nixVectorInCache = GetNixVector (source, dest, nullptr);
- // cache it
- m_nixCache.insert (typename NixMap_t::value_type (dest, nixVectorInCache));
}
if (nixVectorInCache || (!nixVectorInCache && source == destNode))
@@ -1271,7 +1289,7 @@ NixVectorRouting::PrintRoutingPath (Ptr source, IpAddress dest,
*os << *nixVector;
}
- *os << ")" << std::endl;
+ *os << std::endl;
if (source == destNode)
{
@@ -1349,6 +1367,7 @@ NixVectorRouting::CheckCacheStateAndFlush (void) const
if (g_isCacheDirty)
{
FlushGlobalNixRoutingCache ();
+ g_epoch++;
g_isCacheDirty = false;
}
}
diff --git a/src/nix-vector-routing/model/nix-vector-routing.h b/src/nix-vector-routing/model/nix-vector-routing.h
index 28991022b..26f3010a4 100644
--- a/src/nix-vector-routing/model/nix-vector-routing.h
+++ b/src/nix-vector-routing/model/nix-vector-routing.h
@@ -448,6 +448,11 @@ private:
*/
static bool g_isCacheDirty;
+ /**
+ * Nix Epoch, incremented each time a flush is perfomed.
+ */
+ static uint32_t g_epoch;
+
/** Cache stores nix-vectors based on destination ip */
mutable NixMap_t m_nixCache;
diff --git a/src/nix-vector-routing/test/nix-test.cc b/src/nix-vector-routing/test/nix-test.cc
index bb3b3304a..4e5e56247 100644
--- a/src/nix-vector-routing/test/nix-test.cc
+++ b/src/nix-vector-routing/test/nix-test.cc
@@ -312,21 +312,21 @@ NixVectorRoutingTest::DoRun (void)
// Test the Path
const std::string p_nSrcnAnCnDstv4 = "Time: +3s, Nix Routing\n"
- "Route Path: (Node 0 to Node 4, Nix Vector: 01001)\n"
+ "Route path from Node 0 to Node 4, Nix Vector: 01001 (5 bits left)\n"
"10.1.0.1 (Node 0) ----> 10.1.0.2 (Node 1)\n"
"10.1.4.1 (Node 1) ----> 10.1.4.2 (Node 3)\n"
"10.1.3.1 (Node 3) ----> 10.1.3.2 (Node 4)\n\n";
NS_TEST_EXPECT_MSG_EQ (stringStream1v4.str (), p_nSrcnAnCnDstv4, "Routing Path is incorrect.");
const std::string p_nSrcnAnCnDstv6 = "Time: +3s, Nix Routing\n"
- "Route Path: (Node 0 to Node 4, Nix Vector: 01001)\n"
+ "Route path from Node 0 to Node 4, Nix Vector: 01001 (5 bits left)\n"
"2001::200:ff:fe00:1 (Node 0) ----> fe80::200:ff:fe00:2 (Node 1)\n"
"fe80::200:ff:fe00:9 (Node 1) ----> fe80::200:ff:fe00:a (Node 3)\n"
"fe80::200:ff:fe00:7 (Node 3) ----> 2001:3::200:ff:fe00:8 (Node 4)\n\n";
NS_TEST_EXPECT_MSG_EQ (stringStream1v6.str (), p_nSrcnAnCnDstv6, "Routing Path is incorrect.");
const std::string p_nSrcnAnBnCnDstv4 = "Time: +9s, Nix Routing\n"
- "Route Path: (Node 0 to Node 4, Nix Vector: 0111)\n"
+ "Route path from Node 0 to Node 4, Nix Vector: 0111 (4 bits left)\n"
"10.1.0.1 (Node 0) ----> 10.1.0.2 (Node 1)\n"
"10.1.1.1 (Node 1) ----> 10.1.1.2 (Node 2)\n"
"10.1.2.1 (Node 2) ----> 10.1.2.2 (Node 3)\n"
@@ -334,7 +334,7 @@ NixVectorRoutingTest::DoRun (void)
NS_TEST_EXPECT_MSG_EQ (stringStream3v4.str (), p_nSrcnAnBnCnDstv4, "Routing Path is incorrect.");
const std::string p_nSrcnAnBnCnDstv6 = "Time: +9s, Nix Routing\n"
- "Route Path: (Node 0 to Node 4, Nix Vector: 0111)\n"
+ "Route path from Node 0 to Node 4, Nix Vector: 0111 (4 bits left)\n"
"2001::200:ff:fe00:1 (Node 0) ----> fe80::200:ff:fe00:2 (Node 1)\n"
"fe80::200:ff:fe00:3 (Node 1) ----> fe80::200:ff:fe00:4 (Node 2)\n"
"fe80::200:ff:fe00:5 (Node 2) ----> fe80::200:ff:fe00:6 (Node 3)\n"