sixlowpan: add context-based (stateful) IPHC compression
This commit is contained in:
@@ -26,6 +26,7 @@ requirements (Note: not all ns-3 features are available on all systems):
|
||||
|
||||
New user-visible features
|
||||
-------------------------
|
||||
- (sixlowpan) Added support for stateful (i.e., context-based) RFC6282 compression.
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
|
||||
@@ -23,17 +23,15 @@ standpoint, as it does extend it beyond the original scope by supporting also
|
||||
other kinds of networks.
|
||||
|
||||
Other than that, the module strictly follows :rfc:`4944` and :rfc:`6282`, with the
|
||||
following exceptions:
|
||||
|
||||
* HC2 encoding is not supported
|
||||
* IPHC's SAC and DAC are not supported
|
||||
|
||||
The HC2 encoding is not supported, as it has been superseded by IPHC and NHC
|
||||
exception that HC2 encoding is not supported, as it has been superseded by IPHC and NHC
|
||||
compression type (\ :rfc:`6282`).
|
||||
|
||||
IPHC SAC and DAC are not yet supported, as they do require :rfc:`6775`
|
||||
IPHC sateful (context-based) compression is supported but, since :rfc:`6775`
|
||||
("Neighbor Discovery Optimization for IPv6 over Low-Power Wireless Personal Area Networks (6LoWPANs)")
|
||||
for full compliance. It is planned to support them in the future.
|
||||
is not yet implemented, it is necessary to add the context to the nodes manually.
|
||||
|
||||
This is possible though the ``SixLowPanHelper::AddContext`` function.
|
||||
Mind that installing different contexts in different nodes will lead to decompression failures.
|
||||
|
||||
NetDevice
|
||||
#########
|
||||
@@ -117,8 +115,9 @@ Scope and Limitations
|
||||
Contex-based compression
|
||||
########################
|
||||
|
||||
The present implementation does not support context-based (stateful) compression.
|
||||
This limitation will be removed in the future.
|
||||
IPHC sateful (context-based) compression is supported but, since :rfc:`6775`
|
||||
("Neighbor Discovery Optimization for IPv6 over Low-Power Wireless Personal Area Networks (6LoWPANs)")
|
||||
is not yet implemented, it is necessary to add the context to the nodes manually.
|
||||
|
||||
6LoWPAM-ND
|
||||
##########
|
||||
|
||||
@@ -66,6 +66,66 @@ NetDeviceContainer SixLowPanHelper::Install (const NetDeviceContainer c)
|
||||
return devs;
|
||||
}
|
||||
|
||||
void SixLowPanHelper::AddContext (NetDeviceContainer c, uint8_t contextId, Ipv6Prefix context, Time validity)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << +contextId << context << validity);
|
||||
|
||||
for (uint32_t i = 0; i < c.GetN (); ++i)
|
||||
{
|
||||
Ptr<NetDevice> device = c.Get (i);
|
||||
Ptr<SixLowPanNetDevice> sixDevice = DynamicCast<SixLowPanNetDevice> (device);
|
||||
if (sixDevice)
|
||||
{
|
||||
sixDevice->AddContext (contextId, context, true, validity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SixLowPanHelper::RenewContext (NetDeviceContainer c, uint8_t contextId, Time validity)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << +contextId << validity);
|
||||
|
||||
for (uint32_t i = 0; i < c.GetN (); ++i)
|
||||
{
|
||||
Ptr<NetDevice> device = c.Get (i);
|
||||
Ptr<SixLowPanNetDevice> sixDevice = DynamicCast<SixLowPanNetDevice> (device);
|
||||
if (sixDevice)
|
||||
{
|
||||
sixDevice->RenewContext (contextId, validity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SixLowPanHelper::InvalidateContext (NetDeviceContainer c, uint8_t contextId)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << +contextId);
|
||||
|
||||
for (uint32_t i = 0; i < c.GetN (); ++i)
|
||||
{
|
||||
Ptr<NetDevice> device = c.Get (i);
|
||||
Ptr<SixLowPanNetDevice> sixDevice = DynamicCast<SixLowPanNetDevice> (device);
|
||||
if (sixDevice)
|
||||
{
|
||||
sixDevice->InvalidateContext (contextId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SixLowPanHelper::RemoveContext (NetDeviceContainer c, uint8_t contextId)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << +contextId);
|
||||
|
||||
for (uint32_t i = 0; i < c.GetN (); ++i)
|
||||
{
|
||||
Ptr<NetDevice> device = c.Get (i);
|
||||
Ptr<SixLowPanNetDevice> sixDevice = DynamicCast<SixLowPanNetDevice> (device);
|
||||
if (sixDevice)
|
||||
{
|
||||
sixDevice->RemoveContext (contextId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int64_t SixLowPanHelper::AssignStreams (NetDeviceContainer c, int64_t stream)
|
||||
{
|
||||
int64_t currentStream = stream;
|
||||
|
||||
@@ -80,16 +80,64 @@ public:
|
||||
NetDeviceContainer Install (NetDeviceContainer c);
|
||||
|
||||
/**
|
||||
* Assign a fixed random variable stream number to the random variables
|
||||
* used by this model. Return the number of streams (possibly zero) that
|
||||
* have been assigned. The Install() method should have previously been
|
||||
* called by the user.
|
||||
*
|
||||
* \param [in] c NetDeviceContainer of the set of net devices for which the
|
||||
* SixLowPanNetDevice should be modified to use a fixed stream.
|
||||
* \param [in] stream First stream index to use.
|
||||
* \return The number of stream indices assigned by this helper.
|
||||
*/
|
||||
* \brief Adds a compression Context to a set of NetDevices.
|
||||
*
|
||||
* This function installs one Compression Context on a set of NetDevices.
|
||||
* The context is used only in IPHC compression and decompression.
|
||||
*
|
||||
* \param [in] c The NetDevice container.
|
||||
* \param [in] id The context id (must be less than 16).
|
||||
* \param [in] prefix The context prefix.
|
||||
* \param [in] validity the context validity time (relative to the actual time).
|
||||
*/
|
||||
void AddContext (NetDeviceContainer c, uint8_t contextId, Ipv6Prefix context, Time validity);
|
||||
|
||||
/**
|
||||
* \brief Renew a compression Context in a set of NetDevices.
|
||||
*
|
||||
* The context will have its lifetime extended and its validity for compression re-enabled.
|
||||
*
|
||||
* \param [in] c The NetDevice container.
|
||||
* \param [in] id The context id (must be less than 16).
|
||||
* \param [in] validity the context validity time (relative to the actual time).
|
||||
*/
|
||||
void RenewContext (NetDeviceContainer c, uint8_t contextId, Time validity);
|
||||
|
||||
/**
|
||||
* \brief Invalidates a compression Context in a set of NetDevices.
|
||||
*
|
||||
* An invalid context is used only in IPHC decompression and not
|
||||
* in IPHC compression.
|
||||
*
|
||||
* This is necessary to avoid that a context reaching its validity lifetime
|
||||
* can not be used for decompression whie packets are traveling the network.
|
||||
*
|
||||
* \param [in] c The NetDevice container.
|
||||
* \param [in] id The context id (must be less than 16).
|
||||
*/
|
||||
void InvalidateContext (NetDeviceContainer c, uint8_t contextId);
|
||||
|
||||
/**
|
||||
* \brief Remove a compression Context in a set of NetDevices.
|
||||
*
|
||||
* The context is removed immediately from the contexts in the devices.
|
||||
*
|
||||
* \param [in] c The NetDevice container.
|
||||
* \param [in] id The context id (must be less than 16).
|
||||
*/
|
||||
void RemoveContext (NetDeviceContainer c, uint8_t contextId);
|
||||
|
||||
/**
|
||||
* Assign a fixed random variable stream number to the random variables
|
||||
* used by this model. Return the number of streams (possibly zero) that
|
||||
* have been assigned. The Install() method should have previously been
|
||||
* called by the user.
|
||||
*
|
||||
* \param [in] c NetDeviceContainer of the set of net devices for which the
|
||||
* SixLowPanNetDevice should be modified to use a fixed stream.
|
||||
* \param [in] stream First stream index to use.
|
||||
* \return The number of stream indices assigned by this helper.
|
||||
*/
|
||||
int64_t AssignStreams (NetDeviceContainer c, int64_t stream);
|
||||
|
||||
private:
|
||||
|
||||
@@ -793,6 +793,7 @@ SixLowPanIphc::SixLowPanIphc ()
|
||||
{
|
||||
// 011x xxxx xxxx xxxx
|
||||
m_baseFormat = 0x6000;
|
||||
m_srcdstContextId = 0;
|
||||
}
|
||||
|
||||
SixLowPanIphc::SixLowPanIphc (uint8_t dispatch)
|
||||
@@ -800,6 +801,7 @@ SixLowPanIphc::SixLowPanIphc (uint8_t dispatch)
|
||||
// 011x xxxx xxxx xxxx
|
||||
m_baseFormat = dispatch;
|
||||
m_baseFormat <<= 8;
|
||||
m_srcdstContextId = 0;
|
||||
}
|
||||
|
||||
TypeId SixLowPanIphc::GetTypeId (void)
|
||||
@@ -818,7 +820,48 @@ TypeId SixLowPanIphc::GetInstanceTypeId (void) const
|
||||
|
||||
void SixLowPanIphc::Print (std::ostream & os) const
|
||||
{
|
||||
os << "Compression kind: " << +m_baseFormat;
|
||||
switch ( GetTf () )
|
||||
{
|
||||
case TF_FULL:
|
||||
os << "TF_FULL(" << +m_ecn << ", " << +m_dscp << ", " << m_flowLabel << ")";
|
||||
break;
|
||||
case TF_DSCP_ELIDED:
|
||||
os << "TF_DSCP_ELIDED(" << +m_ecn << ", " << m_flowLabel << ")";
|
||||
break;
|
||||
case TF_FL_ELIDED:
|
||||
os << "TF_FL_ELIDED(" << +m_ecn << ", " << +m_dscp << ")";
|
||||
break;
|
||||
default:
|
||||
os << "TF_ELIDED";
|
||||
break;
|
||||
}
|
||||
|
||||
GetNh () ? os << " NH(1)" : os << " NH(0)";
|
||||
|
||||
switch ( GetHlim () )
|
||||
{
|
||||
case HLIM_INLINE:
|
||||
os << " HLIM_INLINE(" << +m_hopLimit << ")";
|
||||
break;
|
||||
case HLIM_COMPR_1:
|
||||
os << " HLIM_COMPR_1(1)";
|
||||
break;
|
||||
case HLIM_COMPR_64:
|
||||
os << " HLIM_COMPR_64(64)";
|
||||
break;
|
||||
default:
|
||||
os << " HLIM_COMPR_255(255)";
|
||||
break;
|
||||
}
|
||||
|
||||
GetCid () ? os << " CID(" << +m_srcdstContextId << ")" : os << " CID(0)";
|
||||
|
||||
GetSac () ? os << " SAC(1)" : os << " SAC(0)";
|
||||
os << " SAM (" << GetSam () << ")";
|
||||
|
||||
GetM () ? os << " M(1)" : os << " M(0)";
|
||||
GetDac () ? os << " DAC(1)" : os << " DAC(0)";
|
||||
os << " DAM (" << GetDam () << ")";
|
||||
}
|
||||
|
||||
uint32_t SixLowPanIphc::GetSerializedSize () const
|
||||
@@ -983,22 +1026,17 @@ void SixLowPanIphc::Serialize (Buffer::Iterator start) const
|
||||
// Source Address
|
||||
switch (GetSam () )
|
||||
{
|
||||
uint8_t temp[16];
|
||||
case HC_INLINE:
|
||||
if ( GetSac () == false )
|
||||
{
|
||||
uint8_t temp[16];
|
||||
m_srcAddress.Serialize (temp);
|
||||
i.Write (temp, 16);
|
||||
i.Write (m_srcInlinePart, 16);
|
||||
}
|
||||
break;
|
||||
case HC_COMPR_64:
|
||||
m_srcAddress.Serialize (temp);
|
||||
i.Write (temp + 8, 8);
|
||||
i.Write (m_srcInlinePart, 8);
|
||||
break;
|
||||
case HC_COMPR_16:
|
||||
m_srcAddress.Serialize (temp);
|
||||
i.Write (temp + 14, 2);
|
||||
i.Write (m_srcInlinePart, 2);
|
||||
break;
|
||||
case HC_COMPR_0:
|
||||
default:
|
||||
@@ -1007,23 +1045,17 @@ void SixLowPanIphc::Serialize (Buffer::Iterator start) const
|
||||
// Destination Address
|
||||
if ( GetM () == false)
|
||||
{
|
||||
uint8_t temp[16];
|
||||
// unicast
|
||||
switch (GetDam () )
|
||||
{
|
||||
case HC_INLINE:
|
||||
if ( GetDac () == false )
|
||||
{
|
||||
m_dstAddress.Serialize (temp);
|
||||
i.Write (temp, 16);
|
||||
}
|
||||
i.Write (m_dstInlinePart, 16);
|
||||
break;
|
||||
case HC_COMPR_64:
|
||||
m_dstAddress.Serialize (temp);
|
||||
i.Write (temp + 8, 8);
|
||||
i.Write (m_dstInlinePart, 8);
|
||||
break;
|
||||
case HC_COMPR_16:
|
||||
m_dstAddress.Serialize (temp);
|
||||
i.Write (temp + 14, 2);
|
||||
i.Write (m_dstInlinePart, 2);
|
||||
break;
|
||||
case HC_COMPR_0:
|
||||
default:
|
||||
@@ -1032,45 +1064,22 @@ void SixLowPanIphc::Serialize (Buffer::Iterator start) const
|
||||
}
|
||||
else
|
||||
{
|
||||
// multicast
|
||||
switch (GetDam () )
|
||||
{
|
||||
uint8_t temp[16];
|
||||
case HC_INLINE:
|
||||
if ( GetDac () == false )
|
||||
{
|
||||
m_dstAddress.Serialize (temp);
|
||||
i.Write (temp, 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_dstAddress.Serialize (temp);
|
||||
i.Write (temp + 1, 2);
|
||||
i.Write (temp + 12, 4);
|
||||
}
|
||||
i.Write (m_dstInlinePart, 16);
|
||||
break;
|
||||
case HC_COMPR_64:
|
||||
if ( GetDac () == false )
|
||||
{
|
||||
m_dstAddress.Serialize (temp);
|
||||
i.Write (temp + 1, 1);
|
||||
i.Write (temp + 11, 5);
|
||||
}
|
||||
i.Write (m_dstInlinePart, 6);
|
||||
break;
|
||||
case HC_COMPR_16:
|
||||
if ( GetDac () == false )
|
||||
{
|
||||
m_dstAddress.Serialize (temp);
|
||||
i.Write (temp + 1, 1);
|
||||
i.Write (temp + 13, 3);
|
||||
}
|
||||
i.Write (m_dstInlinePart, 4);
|
||||
break;
|
||||
case HC_COMPR_0:
|
||||
default:
|
||||
if ( GetDac () == false )
|
||||
{
|
||||
m_dstAddress.Serialize (temp);
|
||||
i.WriteU8 (temp[15]);
|
||||
}
|
||||
i.Write (m_dstInlinePart, 1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1086,6 +1095,10 @@ uint32_t SixLowPanIphc::Deserialize (Buffer::Iterator start)
|
||||
{
|
||||
m_srcdstContextId = i.ReadU8 ();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_srcdstContextId = 0;
|
||||
}
|
||||
// Traffic Class and Flow Label
|
||||
switch ( GetTf () )
|
||||
{
|
||||
@@ -1142,68 +1155,41 @@ uint32_t SixLowPanIphc::Deserialize (Buffer::Iterator start)
|
||||
|
||||
}
|
||||
// Source Address
|
||||
memset (m_srcInlinePart, 0x00, sizeof (m_srcInlinePart));
|
||||
switch (GetSam () )
|
||||
{
|
||||
uint8_t temp[16];
|
||||
case HC_INLINE:
|
||||
if ( GetSac () == false )
|
||||
{
|
||||
i.Read (temp, 16);
|
||||
m_srcAddress = Ipv6Address::Deserialize (temp);
|
||||
i.Read (m_srcInlinePart, 16);
|
||||
}
|
||||
break;
|
||||
case HC_COMPR_64:
|
||||
memset (temp, 0x00, sizeof (temp));
|
||||
i.Read (temp + 8, 8);
|
||||
temp[0] = 0xfe;
|
||||
temp[1] = 0x80;
|
||||
m_srcAddress = Ipv6Address::Deserialize (temp);
|
||||
i.Read (m_srcInlinePart, 8);
|
||||
break;
|
||||
case HC_COMPR_16:
|
||||
memset (temp, 0x00, sizeof (temp));
|
||||
i.Read (temp + 14, 2);
|
||||
temp[0] = 0xfe;
|
||||
temp[1] = 0x80;
|
||||
temp[11] = 0xff;
|
||||
temp[12] = 0xfe;
|
||||
m_srcAddress = Ipv6Address::Deserialize (temp);
|
||||
i.Read (m_srcInlinePart, 2);
|
||||
break;
|
||||
case HC_COMPR_0:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if ( GetSac () == true )
|
||||
{
|
||||
PostProcessSac ();
|
||||
}
|
||||
|
||||
// Destination Address
|
||||
memset (m_dstInlinePart, 0x00, sizeof (m_dstInlinePart));
|
||||
if ( GetM () == false)
|
||||
{
|
||||
uint8_t temp[16];
|
||||
// unicast
|
||||
switch (GetDam () )
|
||||
{
|
||||
case HC_INLINE:
|
||||
if ( GetDac () == false )
|
||||
{
|
||||
i.Read (temp, 16);
|
||||
m_dstAddress = Ipv6Address::Deserialize (temp);
|
||||
}
|
||||
i.Read (m_dstInlinePart, 16);
|
||||
break;
|
||||
case HC_COMPR_64:
|
||||
memset (temp, 0x00, sizeof (temp));
|
||||
i.Read (temp + 8, 8);
|
||||
temp[0] = 0xfe;
|
||||
temp[1] = 0x80;
|
||||
m_dstAddress = Ipv6Address::Deserialize (temp);
|
||||
i.Read (m_dstInlinePart, 8);
|
||||
break;
|
||||
case HC_COMPR_16:
|
||||
memset (temp, 0x00, sizeof (temp));
|
||||
i.Read (temp + 14, 2);
|
||||
temp[0] = 0xfe;
|
||||
temp[1] = 0x80;
|
||||
temp[11] = 0xff;
|
||||
temp[12] = 0xfe;
|
||||
m_dstAddress = Ipv6Address::Deserialize (temp);
|
||||
i.Read (m_dstInlinePart, 2);
|
||||
break;
|
||||
case HC_COMPR_0:
|
||||
default:
|
||||
@@ -1212,61 +1198,26 @@ uint32_t SixLowPanIphc::Deserialize (Buffer::Iterator start)
|
||||
}
|
||||
else
|
||||
{
|
||||
// multicast
|
||||
switch (GetDam () )
|
||||
{
|
||||
uint8_t temp[16];
|
||||
case HC_INLINE:
|
||||
if ( GetDac () == false )
|
||||
{
|
||||
i.Read (temp, 16);
|
||||
m_dstAddress = Ipv6Address::Deserialize (temp);
|
||||
}
|
||||
else
|
||||
{
|
||||
memset (temp, 0x00, sizeof (temp));
|
||||
i.Read (temp + 1, 2);
|
||||
i.Read (temp + 12, 4);
|
||||
temp[0] = 0xff;
|
||||
m_dstAddress = Ipv6Address::Deserialize (temp);
|
||||
}
|
||||
i.Read (m_dstInlinePart, 16);
|
||||
break;
|
||||
case HC_COMPR_64:
|
||||
if ( GetDac () == false )
|
||||
{
|
||||
memset (temp, 0x00, sizeof (temp));
|
||||
i.Read (temp + 1, 1);
|
||||
i.Read (temp + 11, 5);
|
||||
temp[0] = 0xff;
|
||||
m_dstAddress = Ipv6Address::Deserialize (temp);
|
||||
}
|
||||
i.Read (m_dstInlinePart, 6);
|
||||
break;
|
||||
case HC_COMPR_16:
|
||||
if ( GetDac () == false )
|
||||
{
|
||||
memset (temp, 0x00, sizeof (temp));
|
||||
i.Read (temp + 1, 1);
|
||||
i.Read (temp + 13, 3);
|
||||
temp[0] = 0xff;
|
||||
m_dstAddress = Ipv6Address::Deserialize (temp);
|
||||
}
|
||||
i.Read (m_dstInlinePart, 4);
|
||||
break;
|
||||
case HC_COMPR_0:
|
||||
i.Read (m_dstInlinePart, 1);
|
||||
break;
|
||||
default:
|
||||
if ( GetDac () == false )
|
||||
{
|
||||
memset (temp, 0x00, sizeof (temp));
|
||||
temp[15] = i.ReadU8 ();
|
||||
temp[0] = 0xff;
|
||||
temp[1] = 0x02;
|
||||
m_dstAddress = Ipv6Address::Deserialize (temp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( GetDac () == true )
|
||||
{
|
||||
PostProcessDac ();
|
||||
}
|
||||
|
||||
return GetSerializedSize ();
|
||||
}
|
||||
|
||||
@@ -1336,6 +1287,19 @@ SixLowPanIphc::HeaderCompression_e SixLowPanIphc::GetSam (void) const
|
||||
return HeaderCompression_e ((m_baseFormat >> 4) & 0x3);
|
||||
}
|
||||
|
||||
const uint8_t* SixLowPanIphc::GetSrcInlinePart (void) const
|
||||
{
|
||||
return m_srcInlinePart;
|
||||
}
|
||||
|
||||
void SixLowPanIphc::SetSrcInlinePart (uint8_t srcInlinePart[16], uint8_t size)
|
||||
{
|
||||
NS_ASSERT_MSG (size <= 16, "Src inline part too large");
|
||||
|
||||
memcpy (m_srcInlinePart, srcInlinePart, size);
|
||||
return;
|
||||
}
|
||||
|
||||
void SixLowPanIphc::SetM (bool mField)
|
||||
{
|
||||
uint16_t field = mField;
|
||||
@@ -1369,6 +1333,19 @@ SixLowPanIphc::HeaderCompression_e SixLowPanIphc::GetDam (void) const
|
||||
return HeaderCompression_e (m_baseFormat & 0x3);
|
||||
}
|
||||
|
||||
const uint8_t* SixLowPanIphc::GetDstInlinePart (void) const
|
||||
{
|
||||
return m_dstInlinePart;
|
||||
}
|
||||
|
||||
void SixLowPanIphc::SetDstInlinePart (uint8_t dstInlinePart[16], uint8_t size)
|
||||
{
|
||||
NS_ASSERT_MSG (size <= 16, "Dst inline part too large");
|
||||
|
||||
memcpy (m_dstInlinePart, dstInlinePart, size);
|
||||
return;
|
||||
}
|
||||
|
||||
void SixLowPanIphc::SetSrcContextId (uint8_t srcContextId)
|
||||
{
|
||||
NS_ASSERT_MSG (srcContextId < 16, "Src Context ID too large");
|
||||
@@ -1444,38 +1421,6 @@ uint8_t SixLowPanIphc::GetHopLimit (void) const
|
||||
return m_hopLimit;
|
||||
}
|
||||
|
||||
void SixLowPanIphc::SetSrcAddress (Ipv6Address srcAddress)
|
||||
{
|
||||
m_srcAddress = srcAddress;
|
||||
}
|
||||
|
||||
Ipv6Address SixLowPanIphc::GetSrcAddress () const
|
||||
{
|
||||
return m_srcAddress;
|
||||
}
|
||||
|
||||
void SixLowPanIphc::SetDstAddress (Ipv6Address dstAddress)
|
||||
{
|
||||
m_dstAddress = dstAddress;
|
||||
}
|
||||
|
||||
Ipv6Address SixLowPanIphc::GetDstAddress () const
|
||||
{
|
||||
return m_dstAddress;
|
||||
}
|
||||
|
||||
void SixLowPanIphc::PostProcessSac ()
|
||||
{
|
||||
NS_ABORT_MSG ("Unsupported; Context destination is not implemented");
|
||||
return;
|
||||
}
|
||||
|
||||
void SixLowPanIphc::PostProcessDac ()
|
||||
{
|
||||
NS_ABORT_MSG ("Unsupported; Context destination is not implemented");
|
||||
return;
|
||||
}
|
||||
|
||||
std::ostream & operator << (std::ostream & os, const SixLowPanIphc & h)
|
||||
{
|
||||
h.Print (os);
|
||||
|
||||
@@ -768,6 +768,19 @@ public:
|
||||
*/
|
||||
HeaderCompression_e GetSam (void) const;
|
||||
|
||||
/**
|
||||
* brief Set the source address inline part
|
||||
* \param srcInlinePart The inline portion of the compressed source address (16 bytes)
|
||||
* \param size The number of inline bytes
|
||||
*/
|
||||
void SetSrcInlinePart (uint8_t srcInlinePart[16], uint8_t size);
|
||||
|
||||
/**
|
||||
* brief Get the source address inline part
|
||||
* \return The inline portion of the compressed source address (16 bytes)
|
||||
*/
|
||||
const uint8_t* GetSrcInlinePart (void) const;
|
||||
|
||||
/**
|
||||
* \brief Set the M (Multicast) compression.
|
||||
* \param [in] mField True if destination is multicast.
|
||||
@@ -805,6 +818,19 @@ public:
|
||||
HeaderCompression_e GetDam (void) const;
|
||||
|
||||
/**
|
||||
* brief Set the destination address inline part
|
||||
* \param dstInlinePart The inline portion of the compressed destination address (16 bytes)
|
||||
* \param size The number of inline bytes
|
||||
*/
|
||||
void SetDstInlinePart (uint8_t dstInlinePart[16], uint8_t size);
|
||||
|
||||
/**
|
||||
* brief Get the destination address inline part
|
||||
* \return The inline portion of the compressed destination address (16 bytes)
|
||||
*/
|
||||
const uint8_t* GetDstInlinePart (void) const;
|
||||
|
||||
/**
|
||||
* \brief Set the SrcContextId.
|
||||
* \param [in] srcContextId Valid values are [0:15].
|
||||
*/
|
||||
@@ -888,51 +914,16 @@ public:
|
||||
*/
|
||||
uint8_t GetHopLimit (void) const;
|
||||
|
||||
/**
|
||||
* \brief Set the Source Address.
|
||||
* \param [in] srcAddress The Source Address.
|
||||
*/
|
||||
void SetSrcAddress (Ipv6Address srcAddress);
|
||||
|
||||
/**
|
||||
* \brief Get the Source Address.
|
||||
* \return The Source Address.
|
||||
*/
|
||||
Ipv6Address GetSrcAddress () const;
|
||||
|
||||
/**
|
||||
* \brief Set the Destination Address.
|
||||
* \param [in] dstAddress The Destination Address.
|
||||
*/
|
||||
void SetDstAddress (Ipv6Address dstAddress);
|
||||
|
||||
/**
|
||||
* \brief Get the Destination Address.
|
||||
* \return The Destination Address.
|
||||
*/
|
||||
Ipv6Address GetDstAddress () const;
|
||||
|
||||
private:
|
||||
uint16_t m_baseFormat; //!< Dispatch + encoding fields.
|
||||
uint8_t m_srcdstContextId; //!< Src and Dst Context ID.
|
||||
uint8_t m_ecn : 2; //!< ECN bits.
|
||||
uint8_t m_dscp : 6; //!< DSCP bits.
|
||||
uint32_t m_flowLabel : 20; //!< Flow Label bits.
|
||||
uint8_t m_nextHeader; //!< Next header.
|
||||
uint8_t m_hopLimit; //!< Hop Limit.
|
||||
Ipv6Address m_srcAddress; //!< Src address.
|
||||
Ipv6Address m_dstAddress; //!< Dst address.
|
||||
|
||||
/**
|
||||
* \brief Post-process the Source address stateful compression
|
||||
* \note Currently unsupported.
|
||||
*/
|
||||
void PostProcessSac ();
|
||||
/**
|
||||
* \brief Post-process the Destination address stateful compression.
|
||||
* \note Currently unsupported.
|
||||
*/
|
||||
void PostProcessDac ();
|
||||
uint16_t m_baseFormat; //!< Dispatch + encoding fields.
|
||||
uint8_t m_srcdstContextId; //!< Src and Dst Context ID.
|
||||
uint8_t m_ecn : 2; //!< ECN bits.
|
||||
uint8_t m_dscp : 6; //!< DSCP bits.
|
||||
uint32_t m_flowLabel : 20; //!< Flow Label bits.
|
||||
uint8_t m_nextHeader; //!< Next header.
|
||||
uint8_t m_hopLimit; //!< Hop Limit.
|
||||
uint8_t m_srcInlinePart[16]; //!< source address inline part.
|
||||
uint8_t m_dstInlinePart[16]; //!< destination address inline part.
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -196,7 +196,6 @@ void SixLowPanNetDevice::ReceiveFromDevice (Ptr<NetDevice> incomingPort,
|
||||
PacketType packetType)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << incomingPort << packet << protocol << src << dst);
|
||||
NS_LOG_DEBUG ("UID is " << packet->GetUid ());
|
||||
|
||||
uint8_t dispatchRawVal = 0;
|
||||
SixLowPanDispatch::Dispatch_e dispatchVal;
|
||||
@@ -349,8 +348,14 @@ void SixLowPanNetDevice::ReceiveFromDevice (Ptr<NetDevice> incomingPort,
|
||||
m_dropTrace (DROP_DISALLOWED_COMPRESSION, copyPkt, m_node->GetObject<SixLowPanNetDevice> (), GetIfIndex ());
|
||||
return;
|
||||
}
|
||||
DecompressLowPanIphc (copyPkt, realSrc, realDst);
|
||||
isPktDecompressed = true;
|
||||
if (DecompressLowPanIphc (copyPkt, realSrc, realDst))
|
||||
{
|
||||
m_dropTrace (DROP_SATETFUL_DECOMPRESSION_PROBLEM, copyPkt, m_node->GetObject<SixLowPanNetDevice> (), GetIfIndex ());
|
||||
}
|
||||
else
|
||||
{
|
||||
isPktDecompressed = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
NS_LOG_DEBUG ("Unsupported 6LoWPAN encoding: dropping.");
|
||||
@@ -711,6 +716,8 @@ SixLowPanNetDevice::CompressLowPanHc1 (Ptr<Packet> packet, Address const &src, A
|
||||
SixLowPanHc1 hc1Header;
|
||||
uint32_t size = 0;
|
||||
|
||||
NS_LOG_DEBUG ( "Original packet: " << *packet << " Size " << packet->GetSize () );
|
||||
|
||||
if ( packet->PeekHeader (ipHeader) != 0 )
|
||||
{
|
||||
packet->RemoveHeader (ipHeader);
|
||||
@@ -922,7 +929,7 @@ SixLowPanNetDevice::DecompressLowPanHc1 (Ptr<Packet> packet, Address const &src,
|
||||
|
||||
packet->AddHeader (ipHeader);
|
||||
|
||||
NS_LOG_DEBUG ( "Rebuilt packet: " << *packet << " Size " << packet->GetSize () );
|
||||
NS_LOG_DEBUG ( "Rebuilt packet: " << *packet << " Size " << packet->GetSize () );
|
||||
}
|
||||
|
||||
uint32_t
|
||||
@@ -934,6 +941,7 @@ SixLowPanNetDevice::CompressLowPanIphc (Ptr<Packet> packet, Address const &src,
|
||||
SixLowPanIphc iphcHeader;
|
||||
uint32_t size = 0;
|
||||
|
||||
NS_LOG_DEBUG ( "Original packet: " << *packet << " Size " << packet->GetSize () << " src: " << src << " dst: " << dst);
|
||||
|
||||
if ( packet->PeekHeader (ipHeader) != 0 )
|
||||
{
|
||||
@@ -1002,7 +1010,6 @@ SixLowPanNetDevice::CompressLowPanIphc (Ptr<Packet> packet, Address const &src,
|
||||
iphcHeader.SetNextHeader (nextHeader);
|
||||
}
|
||||
|
||||
|
||||
// Set the HLIM field
|
||||
if (ipHeader.GetHopLimit () == 1)
|
||||
{
|
||||
@@ -1023,44 +1030,101 @@ SixLowPanNetDevice::CompressLowPanIphc (Ptr<Packet> packet, Address const &src,
|
||||
iphcHeader.SetHopLimit (ipHeader.GetHopLimit ());
|
||||
}
|
||||
|
||||
// \todo Add the check of CID if there is context-based compression
|
||||
// Set the CID field
|
||||
// Set the CID + SAC + DAC fields to their default value
|
||||
iphcHeader.SetCid (false);
|
||||
|
||||
// \todo Add the check of SAC if there is context-based compression
|
||||
// Set the SAC field
|
||||
iphcHeader.SetSac (false);
|
||||
iphcHeader.SetDac (false);
|
||||
|
||||
uint8_t addressBuf[16];
|
||||
uint8_t unicastAddrCheckerBuf[16];
|
||||
Ipv6Address srcAddr = ipHeader.GetSourceAddress ();
|
||||
srcAddr.GetBytes (addressBuf);
|
||||
|
||||
Ipv6Address checker = Ipv6Address ("fe80:0000:0000:0000:0000:00ff:fe00:1");
|
||||
uint8_t unicastAddrCheckerBuf[16];
|
||||
checker.GetBytes (unicastAddrCheckerBuf);
|
||||
uint8_t addressBuf[16];
|
||||
|
||||
// \todo Add the check of SAC if there is context-based compression
|
||||
// Set the Source Address
|
||||
iphcHeader.SetSrcAddress (srcAddr);
|
||||
// This is just to limit the scope of some variables.
|
||||
if (true)
|
||||
{
|
||||
Ipv6Address srcAddr = ipHeader.GetSourceAddress ();
|
||||
uint8_t srcContextId;
|
||||
|
||||
Ipv6Address mySrcAddr = Ipv6Address::MakeAutoconfiguredLinkLocalAddress (src);
|
||||
NS_LOG_LOGIC ("Checking source compression: " << mySrcAddr << " - " << srcAddr );
|
||||
// The "::" address is compressed as a fake stateful compression.
|
||||
if (srcAddr == Ipv6Address::GetAny ())
|
||||
{
|
||||
// No context information is needed.
|
||||
iphcHeader.SetSam (SixLowPanIphc::HC_INLINE);
|
||||
iphcHeader.SetSac (true);
|
||||
}
|
||||
// Check if the address can be compressed with stateful compression
|
||||
else if ( FindUnicastCompressionContext (srcAddr, srcContextId) )
|
||||
{
|
||||
// We can do stateful compression.
|
||||
NS_LOG_LOGIC ("Checking stateful source compression: " << srcAddr );
|
||||
|
||||
if ( mySrcAddr == srcAddr )
|
||||
{
|
||||
iphcHeader.SetSam (SixLowPanIphc::HC_COMPR_0);
|
||||
}
|
||||
else if (memcmp (addressBuf, unicastAddrCheckerBuf, 14) == 0)
|
||||
{
|
||||
iphcHeader.SetSam (SixLowPanIphc::HC_COMPR_16);
|
||||
}
|
||||
else if ( srcAddr.IsLinkLocal () )
|
||||
{
|
||||
iphcHeader.SetSam (SixLowPanIphc::HC_COMPR_64);
|
||||
}
|
||||
else
|
||||
{
|
||||
iphcHeader.SetSam (SixLowPanIphc::HC_INLINE);
|
||||
iphcHeader.SetSac (true);
|
||||
if (srcContextId != 0)
|
||||
{
|
||||
// the default context is zero, no need to explicit it if it's zero
|
||||
iphcHeader.SetSrcContextId (srcContextId);
|
||||
iphcHeader.SetCid (true);
|
||||
}
|
||||
|
||||
// Note that a context might include parts of the EUI-64 (i.e., be as long as 128 bits).
|
||||
|
||||
if (Ipv6Address::MakeAutoconfiguredAddress (src, m_contextTable[srcContextId].contextPrefix) == srcAddr)
|
||||
{
|
||||
iphcHeader.SetSam (SixLowPanIphc::HC_COMPR_0);
|
||||
}
|
||||
else
|
||||
{
|
||||
Ipv6Address cleanedAddr = CleanPrefix (srcAddr, m_contextTable[srcContextId].contextPrefix);
|
||||
uint8_t serializedCleanedAddress[16];
|
||||
cleanedAddr.Serialize (serializedCleanedAddress);
|
||||
|
||||
if ( serializedCleanedAddress[8] == 0x00 && serializedCleanedAddress[9] == 0x00 &&
|
||||
serializedCleanedAddress[10] == 0x00 && serializedCleanedAddress[11] == 0xff &&
|
||||
serializedCleanedAddress[12] == 0xfe && serializedCleanedAddress[13] == 0x00 )
|
||||
{
|
||||
iphcHeader.SetSam (SixLowPanIphc::HC_COMPR_16);
|
||||
iphcHeader.SetSrcInlinePart (serializedCleanedAddress+14, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
iphcHeader.SetSam (SixLowPanIphc::HC_COMPR_64);
|
||||
iphcHeader.SetSrcInlinePart (serializedCleanedAddress+8, 8);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// We must do stateless compression.
|
||||
NS_LOG_LOGIC ("Checking stateless source compression: " << srcAddr );
|
||||
|
||||
srcAddr.GetBytes (addressBuf);
|
||||
|
||||
uint8_t serializedSrcAddress[16];
|
||||
srcAddr.Serialize (serializedSrcAddress);
|
||||
|
||||
if ( srcAddr == Ipv6Address::MakeAutoconfiguredLinkLocalAddress (src) )
|
||||
{
|
||||
iphcHeader.SetSam (SixLowPanIphc::HC_COMPR_0);
|
||||
}
|
||||
else if (memcmp (addressBuf, unicastAddrCheckerBuf, 14) == 0)
|
||||
{
|
||||
iphcHeader.SetSrcInlinePart (serializedSrcAddress+14, 2);
|
||||
iphcHeader.SetSam (SixLowPanIphc::HC_COMPR_16);
|
||||
}
|
||||
else if ( srcAddr.IsLinkLocal () )
|
||||
{
|
||||
iphcHeader.SetSrcInlinePart (serializedSrcAddress+8, 8);
|
||||
iphcHeader.SetSam (SixLowPanIphc::HC_COMPR_64);
|
||||
}
|
||||
else
|
||||
{
|
||||
iphcHeader.SetSrcInlinePart (serializedSrcAddress, 16);
|
||||
iphcHeader.SetSam (SixLowPanIphc::HC_INLINE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set the M field
|
||||
@@ -1073,69 +1137,156 @@ SixLowPanNetDevice::CompressLowPanIphc (Ptr<Packet> packet, Address const &src,
|
||||
iphcHeader.SetM (false);
|
||||
}
|
||||
|
||||
// \todo Add the check of DAC if there is context-based compression
|
||||
// Set the DAC field
|
||||
iphcHeader.SetDac (false);
|
||||
|
||||
Ipv6Address dstAddr = ipHeader.GetDestinationAddress ();
|
||||
dstAddr.GetBytes (addressBuf);
|
||||
|
||||
// \todo Add the check of DAC if there is context-based compression
|
||||
// Set the Destination Address
|
||||
iphcHeader.SetDstAddress (dstAddr);
|
||||
|
||||
Ipv6Address myDstAddr = Ipv6Address::MakeAutoconfiguredLinkLocalAddress (dst);
|
||||
NS_LOG_LOGIC ("Checking destination compression: " << myDstAddr << " - " << dstAddr );
|
||||
|
||||
if ( !iphcHeader.GetM () )
|
||||
// Unicast address
|
||||
// This is just to limit the scope of some variables.
|
||||
if (true)
|
||||
{
|
||||
if ( myDstAddr == dstAddr )
|
||||
Ipv6Address dstAddr = ipHeader.GetDestinationAddress ();
|
||||
dstAddr.GetBytes (addressBuf);
|
||||
|
||||
NS_LOG_LOGIC ("Checking destination compression: " << dstAddr );
|
||||
|
||||
uint8_t serializedDstAddress[16];
|
||||
dstAddr.Serialize (serializedDstAddress);
|
||||
|
||||
if ( !iphcHeader.GetM () )
|
||||
{
|
||||
iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_0);
|
||||
}
|
||||
else if (memcmp (addressBuf, unicastAddrCheckerBuf, 14) == 0)
|
||||
{
|
||||
iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_16);
|
||||
}
|
||||
else if ( dstAddr.IsLinkLocal () )
|
||||
{
|
||||
iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_64);
|
||||
// Unicast address
|
||||
|
||||
uint8_t dstContextId;
|
||||
if ( FindUnicastCompressionContext (dstAddr, dstContextId) )
|
||||
{
|
||||
// We can do stateful compression.
|
||||
NS_LOG_LOGIC ("Checking stateful destination compression: " << dstAddr );
|
||||
|
||||
iphcHeader.SetDac (true);
|
||||
if (dstContextId != 0)
|
||||
{
|
||||
// the default context is zero, no need to explicit it if it's zero
|
||||
iphcHeader.SetDstContextId (dstContextId);
|
||||
iphcHeader.SetCid (true);
|
||||
}
|
||||
|
||||
// Note that a context might include parts of the EUI-64 (i.e., be as long as 128 bits).
|
||||
if (Ipv6Address::MakeAutoconfiguredAddress (dst, m_contextTable[dstContextId].contextPrefix) == dstAddr)
|
||||
{
|
||||
iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_0);
|
||||
}
|
||||
else
|
||||
{
|
||||
Ipv6Address cleanedAddr = CleanPrefix (dstAddr, m_contextTable[dstContextId].contextPrefix);
|
||||
|
||||
uint8_t serializedCleanedAddress[16];
|
||||
cleanedAddr.Serialize (serializedCleanedAddress);
|
||||
|
||||
if ( serializedCleanedAddress[8] == 0x00 && serializedCleanedAddress[9] == 0x00 &&
|
||||
serializedCleanedAddress[10] == 0x00 && serializedCleanedAddress[11] == 0xff &&
|
||||
serializedCleanedAddress[12] == 0xfe && serializedCleanedAddress[13] == 0x00 )
|
||||
{
|
||||
iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_16);
|
||||
iphcHeader.SetDstInlinePart (serializedCleanedAddress+14, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_64);
|
||||
iphcHeader.SetDstInlinePart (serializedCleanedAddress+8, 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_LOGIC ("Checking stateless destination compression: " << dstAddr );
|
||||
|
||||
if ( dstAddr == Ipv6Address::MakeAutoconfiguredLinkLocalAddress (dst) )
|
||||
{
|
||||
iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_0);
|
||||
}
|
||||
else if (memcmp (addressBuf, unicastAddrCheckerBuf, 14) == 0)
|
||||
{
|
||||
iphcHeader.SetDstInlinePart (serializedDstAddress+14, 2);
|
||||
iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_16);
|
||||
}
|
||||
else if ( dstAddr.IsLinkLocal () )
|
||||
{
|
||||
iphcHeader.SetDstInlinePart (serializedDstAddress+8, 8);
|
||||
iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_64);
|
||||
}
|
||||
else
|
||||
{
|
||||
iphcHeader.SetDstInlinePart (serializedDstAddress, 16);
|
||||
iphcHeader.SetDam (SixLowPanIphc::HC_INLINE);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
iphcHeader.SetDam (SixLowPanIphc::HC_INLINE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Multicast address
|
||||
uint8_t multicastAddrCheckerBuf[16];
|
||||
Ipv6Address multicastCheckAddress = Ipv6Address ("ff02::1");
|
||||
multicastCheckAddress.GetBytes (multicastAddrCheckerBuf);
|
||||
// Multicast address
|
||||
|
||||
// The address takes the form ff02::00XX.
|
||||
if ( memcmp (addressBuf, multicastAddrCheckerBuf, 15) == 0 )
|
||||
{
|
||||
iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_0);
|
||||
}
|
||||
// The address takes the form ffXX::00XX:XXXX.
|
||||
// ffXX:0000:0000:0000:0000:0000:00XX:XXXX.
|
||||
else if ( (addressBuf[0] == multicastAddrCheckerBuf[0])
|
||||
&& (memcmp (addressBuf + 2, multicastAddrCheckerBuf + 2, 11) == 0) )
|
||||
{
|
||||
iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_16);
|
||||
}
|
||||
// The address takes the form ffXX::00XX:XXXX:XXXX.
|
||||
// ffXX:0000:0000:0000:0000:00XX:XXXX:XXXX.
|
||||
else if ( (addressBuf[0] == multicastAddrCheckerBuf[0])
|
||||
&& (memcmp (addressBuf + 2, multicastAddrCheckerBuf + 2, 9) == 0) )
|
||||
{
|
||||
iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_64);
|
||||
}
|
||||
else
|
||||
{
|
||||
iphcHeader.SetDam (SixLowPanIphc::HC_INLINE);
|
||||
uint8_t dstContextId;
|
||||
if ( FindMulticastCompressionContext (dstAddr, dstContextId) )
|
||||
{
|
||||
// Stateful compression (only one possible case)
|
||||
|
||||
// ffXX:XXLL:PPPP:PPPP:PPPP:PPPP:XXXX:XXXX
|
||||
uint8_t dstInlinePart[6] = {};
|
||||
dstInlinePart[0] = serializedDstAddress[1];
|
||||
dstInlinePart[1] = serializedDstAddress[2];
|
||||
dstInlinePart[2] = serializedDstAddress[12];
|
||||
dstInlinePart[3] = serializedDstAddress[13];
|
||||
dstInlinePart[4] = serializedDstAddress[14];
|
||||
dstInlinePart[5] = serializedDstAddress[15];
|
||||
|
||||
iphcHeader.SetDac (true);
|
||||
if (dstContextId != 0)
|
||||
{
|
||||
// the default context is zero, no need to explicit it if it's zero
|
||||
iphcHeader.SetDstContextId (dstContextId);
|
||||
iphcHeader.SetCid (true);
|
||||
}
|
||||
iphcHeader.SetDstInlinePart (dstInlinePart, 6);
|
||||
iphcHeader.SetDam (SixLowPanIphc::HC_INLINE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Stateless compression
|
||||
|
||||
uint8_t multicastAddrCheckerBuf[16];
|
||||
Ipv6Address multicastCheckAddress = Ipv6Address ("ff02::1");
|
||||
multicastCheckAddress.GetBytes (multicastAddrCheckerBuf);
|
||||
|
||||
// The address takes the form ff02::00XX.
|
||||
if ( memcmp (addressBuf, multicastAddrCheckerBuf, 15) == 0 )
|
||||
{
|
||||
iphcHeader.SetDstInlinePart (serializedDstAddress+15, 1);
|
||||
iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_0);
|
||||
}
|
||||
// The address takes the form ffXX::00XX:XXXX.
|
||||
// ffXX:0000:0000:0000:0000:0000:00XX:XXXX.
|
||||
else if ( (addressBuf[0] == multicastAddrCheckerBuf[0])
|
||||
&& (memcmp (addressBuf + 2, multicastAddrCheckerBuf + 2, 11) == 0) )
|
||||
{
|
||||
uint8_t dstInlinePart[4] = {};
|
||||
memcpy (dstInlinePart, serializedDstAddress+1, 1);
|
||||
memcpy (dstInlinePart+1, serializedDstAddress+13, 3);
|
||||
iphcHeader.SetDstInlinePart (dstInlinePart, 4);
|
||||
iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_16);
|
||||
}
|
||||
// The address takes the form ffXX::00XX:XXXX:XXXX.
|
||||
// ffXX:0000:0000:0000:0000:00XX:XXXX:XXXX.
|
||||
else if ( (addressBuf[0] == multicastAddrCheckerBuf[0])
|
||||
&& (memcmp (addressBuf + 2, multicastAddrCheckerBuf + 2, 9) == 0) )
|
||||
{
|
||||
uint8_t dstInlinePart[6] = {};
|
||||
memcpy (dstInlinePart, serializedDstAddress+1, 1);
|
||||
memcpy (dstInlinePart+1, serializedDstAddress+11, 5);
|
||||
iphcHeader.SetDstInlinePart (dstInlinePart, 6);
|
||||
iphcHeader.SetDam (SixLowPanIphc::HC_COMPR_64);
|
||||
}
|
||||
else
|
||||
{
|
||||
iphcHeader.SetDstInlinePart (serializedDstAddress, 16);
|
||||
iphcHeader.SetDam (SixLowPanIphc::HC_INLINE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1148,7 +1299,6 @@ SixLowPanNetDevice::CompressLowPanIphc (Ptr<Packet> packet, Address const &src,
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1173,7 +1323,7 @@ SixLowPanNetDevice::CanCompressLowPanNhc (uint8_t nextHeader)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
SixLowPanNetDevice::DecompressLowPanIphc (Ptr<Packet> packet, Address const &src, Address const &dst)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << *packet << src << dst);
|
||||
@@ -1191,29 +1341,99 @@ SixLowPanNetDevice::DecompressLowPanIphc (Ptr<Packet> packet, Address const &src
|
||||
// Source address
|
||||
if ( encoding.GetSac () )
|
||||
{
|
||||
// Source address compression uses stateful, context-based compression.
|
||||
if ( encoding.GetSam () == SixLowPanIphc::HC_INLINE )
|
||||
{
|
||||
ipHeader.SetSourceAddress ( Ipv6Address::GetAny () );
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_ABORT_MSG ("SAC option not yet implemented");
|
||||
uint8_t contextId = encoding.GetSrcContextId ();
|
||||
if (m_contextTable.find (contextId) == m_contextTable.end ())
|
||||
{
|
||||
NS_LOG_LOGIC ("Unknown Source compression context (" << +contextId << "), dropping packet");
|
||||
return true;
|
||||
}
|
||||
if (m_contextTable[contextId].validLifetime < Simulator::Now ())
|
||||
{
|
||||
NS_LOG_LOGIC ("Expired Source compression context (" << +contextId << "), dropping packet");
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t contexPrefix[16];
|
||||
m_contextTable[contextId].contextPrefix.GetBytes(contexPrefix);
|
||||
uint8_t contextLength = m_contextTable[contextId].contextPrefix.GetPrefixLength ();
|
||||
|
||||
uint8_t srcAddress[16] = { };
|
||||
if ( encoding.GetSam () == SixLowPanIphc::HC_COMPR_64 )
|
||||
{
|
||||
memcpy (srcAddress +8, encoding.GetSrcInlinePart (), 8);
|
||||
}
|
||||
else if ( encoding.GetSam () == SixLowPanIphc::HC_COMPR_16 )
|
||||
{
|
||||
srcAddress[11] = 0xff;
|
||||
srcAddress[12] = 0xfe;
|
||||
memcpy (srcAddress +14, encoding.GetSrcInlinePart (), 2);
|
||||
}
|
||||
else // SixLowPanIphc::HC_COMPR_0
|
||||
{
|
||||
Ipv6Address::MakeAutoconfiguredLinkLocalAddress (src).GetBytes (srcAddress);
|
||||
}
|
||||
|
||||
uint8_t bytesToCopy = contextLength / 8;
|
||||
uint8_t bitsToCopy = contextLength % 8;
|
||||
|
||||
// Do not combine the prefix - we want to override the bytes.
|
||||
for (uint8_t i=0; i<bytesToCopy; i++)
|
||||
{
|
||||
srcAddress[i] = contexPrefix[i];
|
||||
}
|
||||
if (bitsToCopy)
|
||||
{
|
||||
uint8_t addressBitMask = (1<<(8-bitsToCopy))-1;
|
||||
uint8_t prefixBitMask = ~addressBitMask;
|
||||
srcAddress[bytesToCopy] = (contexPrefix[bytesToCopy] & prefixBitMask) | (srcAddress[bytesToCopy] & addressBitMask);
|
||||
}
|
||||
ipHeader.SetSourceAddress ( Ipv6Address::Deserialize (srcAddress) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( encoding.GetSam () == SixLowPanIphc::HC_COMPR_0 )
|
||||
// Source address compression uses stateless compression.
|
||||
|
||||
if ( encoding.GetSam () == SixLowPanIphc::HC_INLINE )
|
||||
{
|
||||
uint8_t srcAddress[16] = { };
|
||||
memcpy (srcAddress, encoding.GetSrcInlinePart (), 16);
|
||||
ipHeader.SetSourceAddress ( Ipv6Address::Deserialize (srcAddress) );
|
||||
}
|
||||
else if ( encoding.GetSam () == SixLowPanIphc::HC_COMPR_64 )
|
||||
{
|
||||
uint8_t srcAddress[16] = { };
|
||||
memcpy (srcAddress +8, encoding.GetSrcInlinePart (), 8);
|
||||
srcAddress[0] = 0xfe;
|
||||
srcAddress[1] = 0x80;
|
||||
ipHeader.SetSourceAddress ( Ipv6Address::Deserialize (srcAddress) );
|
||||
}
|
||||
else if ( encoding.GetSam () == SixLowPanIphc::HC_COMPR_16 )
|
||||
{
|
||||
uint8_t srcAddress[16] = { };
|
||||
memcpy (srcAddress +14, encoding.GetSrcInlinePart (), 2);
|
||||
srcAddress[0] = 0xfe;
|
||||
srcAddress[1] = 0x80;
|
||||
srcAddress[11] = 0xff;
|
||||
srcAddress[12] = 0xfe;
|
||||
ipHeader.SetSourceAddress ( Ipv6Address::Deserialize (srcAddress) );
|
||||
}
|
||||
else // SixLowPanIphc::HC_COMPR_0
|
||||
{
|
||||
ipHeader.SetSourceAddress (Ipv6Address::MakeAutoconfiguredLinkLocalAddress (src));
|
||||
}
|
||||
else
|
||||
{
|
||||
ipHeader.SetSourceAddress ( encoding.GetSrcAddress () );
|
||||
}
|
||||
}
|
||||
// Destination address
|
||||
if ( encoding.GetDac () )
|
||||
{
|
||||
// Destination address compression uses stateful, context-based compression.
|
||||
if ((encoding.GetDam () == SixLowPanIphc::HC_INLINE && !encoding.GetM ())
|
||||
|| (encoding.GetDam () == SixLowPanIphc::HC_COMPR_64 && encoding.GetM ())
|
||||
|| (encoding.GetDam () == SixLowPanIphc::HC_COMPR_16 && encoding.GetM ())
|
||||
@@ -1221,20 +1441,139 @@ SixLowPanNetDevice::DecompressLowPanIphc (Ptr<Packet> packet, Address const &src
|
||||
{
|
||||
NS_ABORT_MSG ("Reserved code found");
|
||||
}
|
||||
|
||||
uint8_t contextId = encoding.GetDstContextId ();
|
||||
if (m_contextTable.find (contextId) == m_contextTable.end ())
|
||||
{
|
||||
NS_LOG_LOGIC ("Unknown Destination compression context (" << +contextId << "), dropping packet");
|
||||
return true;
|
||||
}
|
||||
if (m_contextTable[contextId].validLifetime < Simulator::Now ())
|
||||
{
|
||||
NS_LOG_LOGIC ("Expired Destination compression context (" << +contextId << "), dropping packet");
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t contexPrefix[16];
|
||||
m_contextTable[contextId].contextPrefix.GetBytes(contexPrefix);
|
||||
uint8_t contextLength = m_contextTable[contextId].contextPrefix.GetPrefixLength ();
|
||||
|
||||
if (encoding.GetM () == false)
|
||||
{
|
||||
// unicast
|
||||
uint8_t dstAddress[16] = { };
|
||||
if ( encoding.GetDam () == SixLowPanIphc::HC_COMPR_64 )
|
||||
{
|
||||
memcpy (dstAddress +8, encoding.GetDstInlinePart (), 8);
|
||||
}
|
||||
else if ( encoding.GetDam () == SixLowPanIphc::HC_COMPR_16 )
|
||||
{
|
||||
dstAddress[11] = 0xff;
|
||||
dstAddress[12] = 0xfe;
|
||||
memcpy (dstAddress +14, encoding.GetDstInlinePart (), 2);
|
||||
}
|
||||
else // SixLowPanIphc::HC_COMPR_0
|
||||
{
|
||||
Ipv6Address::MakeAutoconfiguredLinkLocalAddress (dst).GetBytes (dstAddress);
|
||||
}
|
||||
|
||||
uint8_t bytesToCopy = m_contextTable[contextId].contextPrefix.GetPrefixLength () / 8;
|
||||
uint8_t bitsToCopy = contextLength % 8;
|
||||
|
||||
// Do not combine the prefix - we want to override the bytes.
|
||||
for (uint8_t i=0; i<bytesToCopy; i++)
|
||||
{
|
||||
dstAddress[i] = contexPrefix[i];
|
||||
}
|
||||
if (bitsToCopy)
|
||||
{
|
||||
uint8_t addressBitMask = (1<<(8-bitsToCopy))-1;
|
||||
uint8_t prefixBitMask = ~addressBitMask;
|
||||
dstAddress[bytesToCopy] = (contexPrefix[bytesToCopy] & prefixBitMask) | (dstAddress[bytesToCopy] & addressBitMask);
|
||||
}
|
||||
ipHeader.SetDestinationAddress ( Ipv6Address::Deserialize (dstAddress) );
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_ABORT_MSG ("DAC option not yet implemented");
|
||||
// multicast
|
||||
// Just one possibility: ffXX:XXLL:PPPP:PPPP:PPPP:PPPP:XXXX:XXXX
|
||||
uint8_t dstAddress[16] = { };
|
||||
dstAddress[0] = 0xff;
|
||||
memcpy (dstAddress +1, encoding.GetDstInlinePart (), 2);
|
||||
dstAddress[3] = contextLength;
|
||||
memcpy (dstAddress +4, contexPrefix, 8);
|
||||
memcpy (dstAddress +12, encoding.GetDstInlinePart ()+2, 4);
|
||||
ipHeader.SetDestinationAddress ( Ipv6Address::Deserialize (dstAddress) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !encoding.GetM () && encoding.GetDam () == SixLowPanIphc::HC_COMPR_0 )
|
||||
// Destination address compression uses stateless compression.
|
||||
if (encoding.GetM () == false)
|
||||
{
|
||||
ipHeader.SetDestinationAddress (Ipv6Address::MakeAutoconfiguredLinkLocalAddress (dst));
|
||||
}
|
||||
// unicast
|
||||
if ( encoding.GetDam () == SixLowPanIphc::HC_INLINE )
|
||||
{
|
||||
uint8_t dstAddress[16] = { };
|
||||
memcpy (dstAddress, encoding.GetDstInlinePart (), 16);
|
||||
ipHeader.SetDestinationAddress ( Ipv6Address::Deserialize (dstAddress) );
|
||||
}
|
||||
else if ( encoding.GetDam () == SixLowPanIphc::HC_COMPR_64 )
|
||||
{
|
||||
uint8_t dstAddress[16] = { };
|
||||
memcpy (dstAddress +8, encoding.GetDstInlinePart (), 8);
|
||||
dstAddress[0] = 0xfe;
|
||||
dstAddress[1] = 0x80;
|
||||
ipHeader.SetDestinationAddress ( Ipv6Address::Deserialize (dstAddress) );
|
||||
}
|
||||
else if ( encoding.GetDam () == SixLowPanIphc::HC_COMPR_16 )
|
||||
{
|
||||
uint8_t dstAddress[16] = { };
|
||||
memcpy (dstAddress +14, encoding.GetDstInlinePart (), 2);
|
||||
dstAddress[0] = 0xfe;
|
||||
dstAddress[1] = 0x80;
|
||||
dstAddress[11] = 0xff;
|
||||
dstAddress[12] = 0xfe;
|
||||
ipHeader.SetDestinationAddress ( Ipv6Address::Deserialize (dstAddress) );
|
||||
}
|
||||
else // SixLowPanIphc::HC_COMPR_0
|
||||
{
|
||||
ipHeader.SetDestinationAddress (Ipv6Address::MakeAutoconfiguredLinkLocalAddress (dst));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ipHeader.SetDestinationAddress ( encoding.GetDstAddress () );
|
||||
// multicast
|
||||
if ( encoding.GetDam () == SixLowPanIphc::HC_INLINE )
|
||||
{
|
||||
uint8_t dstAddress[16] = { };
|
||||
memcpy (dstAddress, encoding.GetDstInlinePart (), 16);
|
||||
ipHeader.SetDestinationAddress ( Ipv6Address::Deserialize (dstAddress) );
|
||||
}
|
||||
else if ( encoding.GetDam () == SixLowPanIphc::HC_COMPR_64 )
|
||||
{
|
||||
uint8_t dstAddress[16] = { };
|
||||
dstAddress[0] = 0xff;
|
||||
memcpy (dstAddress +1, encoding.GetDstInlinePart (), 1);
|
||||
memcpy (dstAddress +11, encoding.GetDstInlinePart ()+1, 5);
|
||||
ipHeader.SetDestinationAddress ( Ipv6Address::Deserialize (dstAddress) );
|
||||
}
|
||||
else if ( encoding.GetDam () == SixLowPanIphc::HC_COMPR_16 )
|
||||
{
|
||||
uint8_t dstAddress[16] = { };
|
||||
dstAddress[0] = 0xff;
|
||||
memcpy (dstAddress +1, encoding.GetDstInlinePart (), 1);
|
||||
memcpy (dstAddress +13, encoding.GetDstInlinePart ()+1, 3);
|
||||
ipHeader.SetDestinationAddress ( Ipv6Address::Deserialize (dstAddress) );
|
||||
}
|
||||
else // SixLowPanIphc::HC_COMPR_0
|
||||
{
|
||||
uint8_t dstAddress[16] = { };
|
||||
dstAddress[0] = 0xff;
|
||||
dstAddress[1] = 0x02;
|
||||
memcpy (dstAddress+15, encoding.GetDstInlinePart (), 1);
|
||||
ipHeader.SetDestinationAddress ( Ipv6Address::Deserialize (dstAddress) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1282,7 +1621,15 @@ SixLowPanNetDevice::DecompressLowPanIphc (Ptr<Packet> packet, Address const &src
|
||||
}
|
||||
else
|
||||
{
|
||||
ipHeader.SetNextHeader (DecompressLowPanNhc (packet, src, dst, ipHeader.GetSourceAddress (), ipHeader.GetDestinationAddress ()));
|
||||
std::pair <uint8_t, bool> retval = DecompressLowPanNhc (packet, src, dst, ipHeader.GetSourceAddress (), ipHeader.GetDestinationAddress ());
|
||||
if ( retval.second == true )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ipHeader.SetNextHeader (retval.first);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1294,8 +1641,9 @@ SixLowPanNetDevice::DecompressLowPanIphc (Ptr<Packet> packet, Address const &src
|
||||
|
||||
packet->AddHeader (ipHeader);
|
||||
|
||||
NS_LOG_DEBUG ( "Rebuilt packet: " << *packet << " Size " << packet->GetSize () );
|
||||
NS_LOG_DEBUG ( "Rebuilt packet: " << *packet << " Size " << packet->GetSize () );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
@@ -1557,7 +1905,7 @@ SixLowPanNetDevice::CompressLowPanNhc (Ptr<Packet> packet, uint8_t headerType, A
|
||||
return size;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
std::pair <uint8_t, bool>
|
||||
SixLowPanNetDevice::DecompressLowPanNhc (Ptr<Packet> packet, Address const &src, Address const &dst, Ipv6Address srcAddress, Ipv6Address dstAddress)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << *packet);
|
||||
@@ -1602,7 +1950,7 @@ SixLowPanNetDevice::DecompressLowPanNhc (Ptr<Packet> packet, Address const &src,
|
||||
}
|
||||
else
|
||||
{
|
||||
blobData [0] = DecompressLowPanNhc (packet, src, dst, srcAddress, dstAddress);
|
||||
blobData [0] = DecompressLowPanNhc (packet, src, dst, srcAddress, dstAddress).first;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1654,7 +2002,7 @@ SixLowPanNetDevice::DecompressLowPanNhc (Ptr<Packet> packet, Address const &src,
|
||||
}
|
||||
else
|
||||
{
|
||||
blobData [0] = DecompressLowPanNhc (packet, src, dst, srcAddress, dstAddress);
|
||||
blobData [0] = DecompressLowPanNhc (packet, src, dst, srcAddress, dstAddress).first;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1686,7 +2034,7 @@ SixLowPanNetDevice::DecompressLowPanNhc (Ptr<Packet> packet, Address const &src,
|
||||
}
|
||||
else
|
||||
{
|
||||
blobData [0] = DecompressLowPanNhc (packet, src, dst, srcAddress, dstAddress);
|
||||
blobData [0] = DecompressLowPanNhc (packet, src, dst, srcAddress, dstAddress).first;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1720,7 +2068,7 @@ SixLowPanNetDevice::DecompressLowPanNhc (Ptr<Packet> packet, Address const &src,
|
||||
}
|
||||
else
|
||||
{
|
||||
blobData [0] = DecompressLowPanNhc (packet, src, dst, srcAddress, dstAddress);
|
||||
blobData [0] = DecompressLowPanNhc (packet, src, dst, srcAddress, dstAddress).first;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1759,7 +2107,11 @@ SixLowPanNetDevice::DecompressLowPanNhc (Ptr<Packet> packet, Address const &src,
|
||||
break;
|
||||
case SixLowPanNhcExtension::EID_IPv6_H:
|
||||
actualHeaderType = Ipv6Header::IPV6_IPV6;
|
||||
DecompressLowPanIphc (packet, src, dst);
|
||||
if (DecompressLowPanIphc (packet, src, dst))
|
||||
{
|
||||
m_dropTrace (DROP_SATETFUL_DECOMPRESSION_PROBLEM, packet, m_node->GetObject<SixLowPanNetDevice> (), GetIfIndex ());
|
||||
return std::pair<uint8_t, bool> (0, true);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
NS_ABORT_MSG ("Trying to decode unknown Extension Header");
|
||||
@@ -1767,7 +2119,7 @@ SixLowPanNetDevice::DecompressLowPanNhc (Ptr<Packet> packet, Address const &src,
|
||||
}
|
||||
|
||||
NS_LOG_DEBUG ( "Rebuilt packet: " << *packet << " Size " << packet->GetSize () );
|
||||
return actualHeaderType;
|
||||
return std::pair<uint8_t, bool> (actualHeaderType, false);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
@@ -2013,7 +2365,11 @@ bool SixLowPanNetDevice::ProcessFragment (Ptr<Packet>& packet, Address const &sr
|
||||
DecompressLowPanHc1 (p, src, dst);
|
||||
break;
|
||||
case SixLowPanDispatch::LOWPAN_IPHC:
|
||||
DecompressLowPanIphc (p, src, dst);
|
||||
if (DecompressLowPanIphc (p, src, dst))
|
||||
{
|
||||
m_dropTrace (DROP_SATETFUL_DECOMPRESSION_PROBLEM, p, m_node->GetObject<SixLowPanNetDevice> (), GetIfIndex ());
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
NS_FATAL_ERROR ("Unsupported 6LoWPAN encoding, exiting.");
|
||||
@@ -2294,6 +2650,205 @@ void SixLowPanNetDevice::HandleTimeout (void)
|
||||
return;
|
||||
}
|
||||
|
||||
void SixLowPanNetDevice::AddContext (uint8_t contextId, Ipv6Prefix contextPrefix, bool compressionAllowed, Time validLifetime)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << +contextId << Ipv6Address::GetOnes ().CombinePrefix (contextPrefix) << contextPrefix << compressionAllowed << validLifetime.As (Time::S));
|
||||
|
||||
if (contextId > 15)
|
||||
{
|
||||
NS_LOG_LOGIC ("Invalid context ID (" << +contextId << "), ignoring");
|
||||
return;
|
||||
}
|
||||
|
||||
if (validLifetime == Time(0))
|
||||
{
|
||||
NS_LOG_LOGIC ("Context (" << +contextId << "), removed (validity time is zero)");
|
||||
m_contextTable.erase (contextId);
|
||||
return;
|
||||
}
|
||||
|
||||
m_contextTable[contextId].contextPrefix = contextPrefix;
|
||||
m_contextTable[contextId].compressionAllowed = compressionAllowed;
|
||||
m_contextTable[contextId].validLifetime = Simulator::Now () + validLifetime;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bool SixLowPanNetDevice::GetContext (uint8_t contextId, Ipv6Prefix& contextPrefix, bool& compressionAllowed, Time& validLifetime)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << +contextId);
|
||||
|
||||
if (contextId > 15)
|
||||
{
|
||||
NS_LOG_LOGIC ("Invalid context ID (" << +contextId << "), ignoring");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_contextTable.find (contextId) == m_contextTable.end ())
|
||||
{
|
||||
NS_LOG_LOGIC ("Context not found (" << +contextId << "), ignoring");
|
||||
return false;
|
||||
}
|
||||
|
||||
contextPrefix = m_contextTable[contextId].contextPrefix;
|
||||
compressionAllowed = m_contextTable[contextId].compressionAllowed;
|
||||
validLifetime = m_contextTable[contextId].validLifetime;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SixLowPanNetDevice::RenewContext (uint8_t contextId, Time validLifetime)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << +contextId << validLifetime.As (Time::S));
|
||||
|
||||
if (contextId > 15)
|
||||
{
|
||||
NS_LOG_LOGIC ("Invalid context ID (" << +contextId << "), ignoring");
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_contextTable.find (contextId) == m_contextTable.end ())
|
||||
{
|
||||
NS_LOG_LOGIC ("Context not found (" << +contextId << "), ignoring");
|
||||
return;
|
||||
}
|
||||
m_contextTable[contextId].compressionAllowed = true;
|
||||
m_contextTable[contextId].validLifetime = Simulator::Now () + validLifetime;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void SixLowPanNetDevice::InvalidateContext (uint8_t contextId)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << +contextId);
|
||||
|
||||
if (contextId > 15)
|
||||
{
|
||||
NS_LOG_LOGIC ("Invalid context ID (" << +contextId << "), ignoring");
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_contextTable.find (contextId) == m_contextTable.end ())
|
||||
{
|
||||
NS_LOG_LOGIC ("Context not found (" << +contextId << "), ignoring");
|
||||
return;
|
||||
}
|
||||
m_contextTable[contextId].compressionAllowed = false;
|
||||
return;
|
||||
}
|
||||
|
||||
void SixLowPanNetDevice::RemoveContext (uint8_t contextId)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << +contextId);
|
||||
|
||||
if (contextId > 15)
|
||||
{
|
||||
NS_LOG_LOGIC ("Invalid context ID (" << +contextId << "), ignoring");
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_contextTable.find (contextId) == m_contextTable.end ())
|
||||
{
|
||||
NS_LOG_LOGIC ("Context not found (" << +contextId << "), ignoring");
|
||||
return;
|
||||
}
|
||||
|
||||
m_contextTable.erase (contextId);
|
||||
return;
|
||||
}
|
||||
|
||||
bool SixLowPanNetDevice::FindUnicastCompressionContext (Ipv6Address address, uint8_t& contextId)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << address);
|
||||
|
||||
for (const auto& iter: m_contextTable)
|
||||
{
|
||||
ContextEntry context = iter.second;
|
||||
|
||||
if ( (context.compressionAllowed == true) && (context.validLifetime > Simulator::Now ()) )
|
||||
{
|
||||
|
||||
if (address.HasPrefix (context.contextPrefix))
|
||||
{
|
||||
NS_LOG_LOGIC ("Fount context " << +contextId << " " <<
|
||||
Ipv6Address::GetOnes ().CombinePrefix (context.contextPrefix) << context.contextPrefix << " matching");
|
||||
|
||||
contextId = iter.first;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SixLowPanNetDevice::FindMulticastCompressionContext (Ipv6Address address, uint8_t& contextId)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << address);
|
||||
|
||||
// The only allowed context-based compressed multicast address is in the form
|
||||
// ffXX:XXLL:PPPP:PPPP:PPPP:PPPP:XXXX:XXXX
|
||||
|
||||
for (const auto& iter: m_contextTable)
|
||||
{
|
||||
ContextEntry context = iter.second;
|
||||
|
||||
if ( (context.compressionAllowed == true) && (context.validLifetime > Simulator::Now ()) )
|
||||
{
|
||||
uint8_t contextLength = context.contextPrefix.GetPrefixLength ();
|
||||
|
||||
if (contextLength <= 64) // only 64-bit prefixes or less are allowed.
|
||||
{
|
||||
uint8_t contextBytes[16];
|
||||
uint8_t addressBytes[16];
|
||||
|
||||
context.contextPrefix.GetBytes (contextBytes);
|
||||
address.GetBytes (addressBytes);
|
||||
|
||||
if (addressBytes[3] == contextLength &&
|
||||
addressBytes[4] == contextBytes[0] &&
|
||||
addressBytes[5] == contextBytes[1] &&
|
||||
addressBytes[6] == contextBytes[2] &&
|
||||
addressBytes[7] == contextBytes[3] &&
|
||||
addressBytes[8] == contextBytes[4] &&
|
||||
addressBytes[9] == contextBytes[5] &&
|
||||
addressBytes[10] == contextBytes[6] &&
|
||||
addressBytes[11] == contextBytes[7])
|
||||
{
|
||||
NS_LOG_LOGIC ("Fount context " << +contextId << " " <<
|
||||
Ipv6Address::GetOnes ().CombinePrefix (context.contextPrefix) << context.contextPrefix << " matching");
|
||||
|
||||
contextId = iter.first;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Ipv6Address SixLowPanNetDevice::CleanPrefix (Ipv6Address address, Ipv6Prefix prefix)
|
||||
{
|
||||
uint8_t addressBytes[16];
|
||||
address.GetBytes (addressBytes);
|
||||
uint8_t prefixLength = prefix.GetPrefixLength ();
|
||||
|
||||
uint8_t bytesToClean = prefixLength / 8;
|
||||
uint8_t bitsToClean = prefixLength % 8;
|
||||
for (uint8_t i=0; i<bytesToClean; i++)
|
||||
{
|
||||
addressBytes[i] = 0;
|
||||
}
|
||||
if (bitsToClean)
|
||||
{
|
||||
uint8_t cleanupMask = (1<<bitsToClean)-1;
|
||||
addressBytes[bytesToClean] &= cleanupMask;
|
||||
}
|
||||
|
||||
Ipv6Address cleanedAddress = Ipv6Address::Deserialize (addressBytes);
|
||||
|
||||
return cleanedAddress;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// namespace ns3
|
||||
|
||||
@@ -70,10 +70,11 @@ public:
|
||||
*/
|
||||
enum DropReason
|
||||
{
|
||||
DROP_FRAGMENT_TIMEOUT = 1, /**< Fragment timeout exceeded */
|
||||
DROP_FRAGMENT_BUFFER_FULL, /**< Fragment buffer size exceeded */
|
||||
DROP_UNKNOWN_EXTENSION, /**< Unsupported compression kind */
|
||||
DROP_DISALLOWED_COMPRESSION /**< HC1 while in IPHC mode or viceversa */
|
||||
DROP_FRAGMENT_TIMEOUT = 1, /**< Fragment timeout exceeded */
|
||||
DROP_FRAGMENT_BUFFER_FULL, /**< Fragment buffer size exceeded */
|
||||
DROP_UNKNOWN_EXTENSION, /**< Unsupported compression kind */
|
||||
DROP_DISALLOWED_COMPRESSION, /**< HC1 while in IPHC mode or viceversa */
|
||||
DROP_SATETFUL_DECOMPRESSION_PROBLEM, /**< Decompression failed due to missing or expired context */
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -162,7 +163,7 @@ public:
|
||||
uint32_t ifindex);
|
||||
|
||||
/**
|
||||
* TracedCallback signature for
|
||||
* TracedCallback signature fo packet drop events
|
||||
*
|
||||
* \param [in] reason The reason for the drop.
|
||||
* \param [in] packet The packet.
|
||||
@@ -177,6 +178,58 @@ public:
|
||||
Ptr<SixLowPanNetDevice> sixNetDevice,
|
||||
uint32_t ifindex);
|
||||
|
||||
/**
|
||||
* Add, remove, or update a context used in IPHC stateful compression.
|
||||
*
|
||||
* A context with a zero validLifetime will be immediately removed.
|
||||
*
|
||||
* \param [in] contextId context id (most be between 0 and 15 included).
|
||||
* \param [in] contextPrefix context prefix to be used in compression/decompression.
|
||||
* \param [in] compressionAllowed compression and decompression allowed (true), decompression only (false).
|
||||
* \param [in] validLifetime validity time (relative to the actual time).
|
||||
*
|
||||
*/
|
||||
void AddContext (uint8_t contextId, Ipv6Prefix contextPrefix, bool compressionAllowed, Time validLifetime);
|
||||
|
||||
/**
|
||||
* Get a context used in IPHC stateful compression.
|
||||
*
|
||||
* \param [in] contextId context id (most be between 0 and 15 included).
|
||||
* \param [out] contextPrefix context prefix to be used in compression/decompression.
|
||||
* \param [out] compressionAllowed compression and decompression allowed (true), decompression only (false).
|
||||
* \param [out] validLifetime validity time (relative to the actual time).
|
||||
*
|
||||
* \return false if the context has not been found.
|
||||
*
|
||||
*/
|
||||
bool GetContext (uint8_t contextId, Ipv6Prefix& contextPrefix, bool& compressionAllowed, Time& validLifetime);
|
||||
|
||||
/**
|
||||
* Renew a context used in IPHC stateful compression.
|
||||
*
|
||||
* The context will have its lifetime extended and its validity for compression re-enabled.
|
||||
*
|
||||
* \param [in] contextId context id (most be between 0 and 15 included).
|
||||
* \param [in] validLifetime validity time (relative to the actual time).
|
||||
*/
|
||||
void RenewContext (uint8_t contextId, Time validLifetime);
|
||||
|
||||
/**
|
||||
* Invalidate a context used in IPHC stateful compression.
|
||||
*
|
||||
* An invalid context will not be used for compression but it will be used for decompression.
|
||||
*
|
||||
* \param [in] contextId context id (most be between 0 and 15 included).
|
||||
*/
|
||||
void InvalidateContext (uint8_t contextId);
|
||||
|
||||
/**
|
||||
* Remove a context used in IPHC stateful compression.
|
||||
*
|
||||
* \param [in] contextId context id (most be between 0 and 15 included).
|
||||
*/
|
||||
void RemoveContext (uint8_t contextId);
|
||||
|
||||
protected:
|
||||
virtual void DoDispose (void);
|
||||
|
||||
@@ -312,8 +365,9 @@ private:
|
||||
* \param [in] packet The packet to be compressed.
|
||||
* \param [in] src The MAC source address.
|
||||
* \param [in] dst The MAC destination address.
|
||||
* \return true if the packet can not be decompressed due to wrong context informations.
|
||||
*/
|
||||
void DecompressLowPanIphc (Ptr<Packet> packet, Address const &src, Address const &dst);
|
||||
bool DecompressLowPanIphc (Ptr<Packet> packet, Address const &src, Address const &dst);
|
||||
|
||||
/**
|
||||
* \brief Compress the headers according to NHC compression.
|
||||
@@ -332,9 +386,9 @@ private:
|
||||
* \param [in] dst The MAC destination address.
|
||||
* \param [in] srcAddress The IPv6 source address.
|
||||
* \param [in] dstAddress The IPv6 destination address.
|
||||
* \return The decompressed header type.
|
||||
* \return A std::pair containing the decompressed header type and a flag - true if the packet can not be decompressed due to wrong context informations.
|
||||
*/
|
||||
uint8_t DecompressLowPanNhc (Ptr<Packet> packet, Address const &src, Address const &dst, Ipv6Address srcAddress, Ipv6Address dstAddress);
|
||||
std::pair<uint8_t, bool> DecompressLowPanNhc (Ptr<Packet> packet, Address const &src, Address const &dst, Ipv6Address srcAddress, Ipv6Address dstAddress);
|
||||
|
||||
/**
|
||||
* \brief Compress the headers according to NHC compression.
|
||||
@@ -549,6 +603,48 @@ private:
|
||||
uint32_t m_compressionThreshold; //!< Minimum L2 payload size.
|
||||
|
||||
Ptr<UniformRandomVariable> m_rng; //!< Rng for the fragments tag.
|
||||
|
||||
/**
|
||||
* Structure holding the informations for a context (used in compression and decompression)
|
||||
*/
|
||||
struct ContextEntry
|
||||
{
|
||||
Ipv6Prefix contextPrefix; //!< context prefix to be used in compression/decompression
|
||||
bool compressionAllowed; //!< compression and decompression allowed (true), decompression only (false)
|
||||
Time validLifetime; //!< validity period
|
||||
};
|
||||
|
||||
std::map<uint8_t, ContextEntry> m_contextTable; //!< Table of the contexts used in compression/decompression
|
||||
|
||||
/**
|
||||
* \brief Finds if the given unicast address matches a context for compression
|
||||
*
|
||||
* \param[in] address the address to check
|
||||
* \param[out] the context found
|
||||
* \return true if a valid context has been found
|
||||
*/
|
||||
bool FindUnicastCompressionContext (Ipv6Address address, uint8_t& contextId);
|
||||
|
||||
/**
|
||||
* \brief Finds if the given multicast address matches a context for compression
|
||||
*
|
||||
* \param[in] address the address to check
|
||||
* \param[out] the context found
|
||||
* \return true if a valid context has been found
|
||||
*/
|
||||
bool FindMulticastCompressionContext (Ipv6Address address, uint8_t& contextId);
|
||||
|
||||
/**
|
||||
* \brief Clean an address from its prefix.
|
||||
*
|
||||
* This function is used to find the relevant bits to be sent in stateful IPHC compression.
|
||||
* Only the pefix length is used - the address prefix is assumed to be matching the prefix.
|
||||
*
|
||||
* \param address the address to be cleaned
|
||||
* \param the prefix to remove
|
||||
* \return An address with the prefix zeroed.
|
||||
*/
|
||||
Ipv6Address CleanPrefix (Ipv6Address address, Ipv6Prefix prefix);
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
348
src/sixlowpan/test/mock-net-device.cc
Normal file
348
src/sixlowpan/test/mock-net-device.cc
Normal file
@@ -0,0 +1,348 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2020 Universita' di Firenze, Italy
|
||||
*
|
||||
* 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: Tommaso Pecorella <tommaso.pecorella@unifi.it>
|
||||
*/
|
||||
#include "mock-net-device.h"
|
||||
#include "ns3/node.h"
|
||||
#include "ns3/packet.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/pointer.h"
|
||||
#include "ns3/trace-source-accessor.h"
|
||||
#include "ns3/boolean.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/channel.h"
|
||||
#include "ns3/mac64-address.h"
|
||||
#include "ns3/mac48-address.h"
|
||||
#include "ns3/mac16-address.h"
|
||||
#include "ns3/mac8-address.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("MockNetDevice");
|
||||
NS_OBJECT_ENSURE_REGISTERED (MockNetDevice);
|
||||
|
||||
TypeId
|
||||
MockNetDevice::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::MockNetDevice")
|
||||
.SetParent<NetDevice> ()
|
||||
.SetGroupName("Network")
|
||||
.AddConstructor<MockNetDevice> ()
|
||||
.AddAttribute ("PointToPointMode",
|
||||
"The device is configured in Point to Point mode",
|
||||
BooleanValue (false),
|
||||
MakeBooleanAccessor (&MockNetDevice::m_pointToPointMode),
|
||||
MakeBooleanChecker ())
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
MockNetDevice::MockNetDevice ()
|
||||
: m_node (0),
|
||||
m_mtu (0xffff),
|
||||
m_ifIndex (0),
|
||||
m_linkUp (true)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
}
|
||||
|
||||
void
|
||||
MockNetDevice::Receive (Ptr<Packet> packet, uint16_t protocol,
|
||||
Address to, Address from, NetDevice::PacketType packetType)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << packet << protocol << to << from);
|
||||
|
||||
if (packetType != NetDevice::PACKET_OTHERHOST)
|
||||
{
|
||||
m_rxCallback (this, packet, protocol, from);
|
||||
}
|
||||
|
||||
if (!m_promiscCallback.IsNull ())
|
||||
{
|
||||
m_promiscCallback (this, packet, protocol, from, to, packetType);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MockNetDevice::SetIfIndex (const uint32_t index)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << index);
|
||||
m_ifIndex = index;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
MockNetDevice::GetIfIndex (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return m_ifIndex;
|
||||
}
|
||||
|
||||
Ptr<Channel>
|
||||
MockNetDevice::GetChannel (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
MockNetDevice::SetAddress (Address address)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << address);
|
||||
m_address = address;
|
||||
}
|
||||
|
||||
Address
|
||||
MockNetDevice::GetAddress (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return m_address;
|
||||
}
|
||||
|
||||
bool
|
||||
MockNetDevice::SetMtu (const uint16_t mtu)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << mtu);
|
||||
m_mtu = mtu;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint16_t
|
||||
MockNetDevice::GetMtu (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return m_mtu;
|
||||
}
|
||||
|
||||
bool
|
||||
MockNetDevice::IsLinkUp (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return m_linkUp;
|
||||
}
|
||||
|
||||
void
|
||||
MockNetDevice::AddLinkChangeCallback (Callback<void> callback)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << &callback);
|
||||
m_linkChangeCallbacks.ConnectWithoutContext (callback);
|
||||
}
|
||||
|
||||
bool
|
||||
MockNetDevice::IsBroadcast (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
if (m_pointToPointMode)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (Mac64Address::IsMatchingType (m_address))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (Mac8Address::IsMatchingType (m_address))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Address
|
||||
MockNetDevice::GetBroadcast (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
Address address;
|
||||
|
||||
if (Mac48Address::IsMatchingType (m_address))
|
||||
{
|
||||
address = Mac48Address::GetBroadcast ();
|
||||
}
|
||||
else if (Mac16Address::IsMatchingType (m_address))
|
||||
{
|
||||
address = Mac16Address::GetBroadcast ();
|
||||
}
|
||||
|
||||
return address;
|
||||
}
|
||||
|
||||
bool
|
||||
MockNetDevice::IsMulticast (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
if (m_pointToPointMode)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (Mac64Address::IsMatchingType (m_address))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (Mac8Address::IsMatchingType (m_address))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Address
|
||||
MockNetDevice::GetMulticast (Ipv4Address multicastGroup) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this << multicastGroup);
|
||||
|
||||
Address address;
|
||||
|
||||
if (Mac48Address::IsMatchingType (m_address))
|
||||
{
|
||||
address = Mac48Address::GetMulticast (multicastGroup);
|
||||
}
|
||||
else if (Mac16Address::IsMatchingType (m_address))
|
||||
{
|
||||
address = Mac16Address::GetMulticast (Ipv6Address::MakeIpv4MappedAddress (multicastGroup));
|
||||
}
|
||||
|
||||
return address;
|
||||
}
|
||||
|
||||
Address MockNetDevice::GetMulticast (Ipv6Address addr) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this << addr);
|
||||
Address address;
|
||||
|
||||
if (Mac48Address::IsMatchingType (m_address))
|
||||
{
|
||||
address = Mac48Address::GetMulticast (addr);
|
||||
}
|
||||
else if (Mac16Address::IsMatchingType (m_address))
|
||||
{
|
||||
address = Mac16Address::GetMulticast (addr);
|
||||
}
|
||||
|
||||
return address;
|
||||
}
|
||||
|
||||
bool
|
||||
MockNetDevice::IsPointToPoint (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
if (m_pointToPointMode)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
MockNetDevice::IsBridge (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
MockNetDevice::Send (Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << packet << dest << protocolNumber);
|
||||
|
||||
return SendFrom (packet, m_address, dest, protocolNumber);
|
||||
}
|
||||
|
||||
bool
|
||||
MockNetDevice::SendFrom (Ptr<Packet> p, const Address& source, const Address& dest, uint16_t protocolNumber)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << p << source << dest << protocolNumber);
|
||||
if (p->GetSize () > GetMtu ())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_sendCallback.IsNull ())
|
||||
{
|
||||
m_sendCallback (this, p, protocolNumber, source, dest, NetDevice::PACKET_HOST);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Ptr<Node>
|
||||
MockNetDevice::GetNode (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return m_node;
|
||||
}
|
||||
void
|
||||
MockNetDevice::SetNode (Ptr<Node> node)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << node);
|
||||
m_node = node;
|
||||
}
|
||||
|
||||
bool
|
||||
MockNetDevice::NeedsArp (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
if (m_pointToPointMode)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
MockNetDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << &cb);
|
||||
m_rxCallback = cb;
|
||||
}
|
||||
|
||||
void
|
||||
MockNetDevice::DoDispose (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_node = 0;
|
||||
m_rxCallback.Nullify ();
|
||||
m_promiscCallback.Nullify ();
|
||||
m_sendCallback.Nullify ();
|
||||
NetDevice::DoDispose ();
|
||||
}
|
||||
|
||||
void
|
||||
MockNetDevice::SetPromiscReceiveCallback (PromiscReceiveCallback cb)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << &cb);
|
||||
m_promiscCallback = cb;
|
||||
}
|
||||
|
||||
bool
|
||||
MockNetDevice::SupportsSendFrom (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
MockNetDevice::SetSendCallback (PromiscReceiveCallback cb)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << &cb);
|
||||
m_sendCallback = cb;
|
||||
}
|
||||
|
||||
|
||||
} // namespace ns3
|
||||
132
src/sixlowpan/test/mock-net-device.h
Normal file
132
src/sixlowpan/test/mock-net-device.h
Normal file
@@ -0,0 +1,132 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2020 Universita' di Firenze, Italy
|
||||
*
|
||||
* 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: Tommaso Pecorella <tommaso.pecorella@unifi.it>
|
||||
*/
|
||||
#ifndef MOCK_NET_DEVICE_H
|
||||
#define MOCK_NET_DEVICE_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
|
||||
#include "ns3/traced-callback.h"
|
||||
#include "ns3/net-device.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
class Node;
|
||||
|
||||
/**
|
||||
* \ingroup netdevice
|
||||
*
|
||||
* This device assumes 48-bit mac addressing; there is also the possibility to
|
||||
* add an ErrorModel if you want to force losses on the device.
|
||||
*
|
||||
* The device can be installed on a node through the MockNetDeviceHelper.
|
||||
* In case of manual creation, the user is responsible for assigning an unique
|
||||
* address to the device.
|
||||
*
|
||||
* By default the device is in Broadcast mode, with infinite bandwidth.
|
||||
*
|
||||
* \brief simple net device for simple things and testing
|
||||
*/
|
||||
class MockNetDevice : public NetDevice
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* \brief Get the type ID.
|
||||
* \return the object TypeId
|
||||
*/
|
||||
static TypeId GetTypeId (void);
|
||||
MockNetDevice ();
|
||||
|
||||
/**
|
||||
* Pretend that a packet has been received from a connected Channel.
|
||||
*
|
||||
* Note that no analysis is performed on the addresses, and the
|
||||
* packet is forwarded to the callbacks according to the packetType.
|
||||
*
|
||||
* \param packet Packet received on the channel
|
||||
* \param protocol protocol number
|
||||
* \param to address packet should be sent to
|
||||
* \param from address packet was sent from
|
||||
* \param packetType type of the packet (e.g., NetDevice::PACKET_HOST, NetDevice::PACKET_OTHERHOST, etc.)
|
||||
*/
|
||||
void Receive (Ptr<Packet> packet, uint16_t protocol, Address to, Address from, NetDevice::PacketType packetType);
|
||||
|
||||
// inherited from NetDevice base class.
|
||||
virtual void SetIfIndex (const uint32_t index);
|
||||
virtual uint32_t GetIfIndex (void) const;
|
||||
virtual Ptr<Channel> GetChannel (void) const;
|
||||
virtual void SetAddress (Address address);
|
||||
virtual Address GetAddress (void) const;
|
||||
virtual bool SetMtu (const uint16_t mtu);
|
||||
virtual uint16_t GetMtu (void) const;
|
||||
virtual bool IsLinkUp (void) const;
|
||||
virtual void AddLinkChangeCallback (Callback<void> callback);
|
||||
virtual bool IsBroadcast (void) const;
|
||||
virtual Address GetBroadcast (void) const;
|
||||
virtual bool IsMulticast (void) const;
|
||||
virtual Address GetMulticast (Ipv4Address multicastGroup) const;
|
||||
virtual Address GetMulticast (Ipv6Address addr) const;
|
||||
virtual bool IsPointToPoint (void) const;
|
||||
virtual bool IsBridge (void) 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 (void) const;
|
||||
virtual void SetNode (Ptr<Node> node);
|
||||
virtual bool NeedsArp (void) const;
|
||||
virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb);
|
||||
virtual void SetPromiscReceiveCallback (PromiscReceiveCallback cb);
|
||||
virtual bool SupportsSendFrom (void) const;
|
||||
|
||||
/**
|
||||
*
|
||||
* Add a callback to be invoked when the MockNetDevice has a packet to "send".
|
||||
*
|
||||
* In the callback the PacketType is always set to NetDevice::PACKET_HOST.
|
||||
*
|
||||
* \param cb callback to invoke whenever the MockNetDevice has one packet to "send".
|
||||
*
|
||||
*/
|
||||
void SetSendCallback (PromiscReceiveCallback cb);
|
||||
|
||||
protected:
|
||||
virtual void DoDispose (void);
|
||||
|
||||
private:
|
||||
|
||||
NetDevice::ReceiveCallback m_rxCallback; //!< Receive callback
|
||||
NetDevice::PromiscReceiveCallback m_promiscCallback; //!< Promiscuous receive callback
|
||||
NetDevice::PromiscReceiveCallback m_sendCallback; //!< Send callback
|
||||
Ptr<Node> m_node; //!< Node this netDevice is associated to
|
||||
uint16_t m_mtu; //!< MTU
|
||||
uint32_t m_ifIndex; //!< Interface index
|
||||
Address m_address; //!< MAC address
|
||||
|
||||
bool m_linkUp; //!< Flag indicating whether or not the link is up
|
||||
bool m_pointToPointMode; //!< Enabling this will disable Broadcast and Arp.
|
||||
|
||||
/**
|
||||
* List of callbacks to fire if the link changes state (up or down).
|
||||
*/
|
||||
TracedCallback<> m_linkChangeCallbacks;
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif /* MOCK_NET_DEVICE_H */
|
||||
313
src/sixlowpan/test/sixlowpan-iphc-stateful-test.cc
Normal file
313
src/sixlowpan/test/sixlowpan-iphc-stateful-test.cc
Normal file
@@ -0,0 +1,313 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2020 Universita' di Firenze, Italy
|
||||
*
|
||||
* 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: Tommaso Pecorella <tommaso.pecorella@unifi.it>
|
||||
*/
|
||||
|
||||
#include "ns3/test.h"
|
||||
#include "ns3/socket-factory.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/socket.h"
|
||||
#include "ns3/boolean.h"
|
||||
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/node.h"
|
||||
#include "ns3/inet6-socket-address.h"
|
||||
#include "ns3/internet-stack-helper.h"
|
||||
#include "ns3/ipv6-address-helper.h"
|
||||
#include "ns3/icmpv6-l4-protocol.h"
|
||||
|
||||
#include "ns3/sixlowpan-net-device.h"
|
||||
#include "ns3/sixlowpan-header.h"
|
||||
#include "ns3/sixlowpan-helper.h"
|
||||
#include "mock-net-device.h"
|
||||
|
||||
#include <string>
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
/**
|
||||
* \ingroup sixlowpan
|
||||
* \defgroup sixlowpan-test 6LoWPAN module tests
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* \ingroup sixlowpan-test
|
||||
* \ingroup tests
|
||||
*
|
||||
* \brief 6LoWPAN IPHC stateful compression Test
|
||||
*/
|
||||
class SixlowpanIphcStatefulImplTest : public TestCase
|
||||
{
|
||||
/**
|
||||
* \brief Structure to hold the Rx/Tx packets.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
Ptr<Packet> packet; /**< Packet data */
|
||||
Address src; /**< Source address */
|
||||
Address dst; /**< Destination address */
|
||||
} Data;
|
||||
|
||||
|
||||
std::vector<Data> m_txPackets; //!< Transmitted packets
|
||||
std::vector<Data> m_rxPackets; //!< Received packets
|
||||
|
||||
bool ReceiveFromMockDevice (Ptr<NetDevice> device, Ptr<const Packet> packet, uint16_t protocol,
|
||||
Address const &source, Address const &destination, NetDevice::PacketType packetType);
|
||||
|
||||
bool PromiscReceiveFromSixLowPanDevice (Ptr<NetDevice> device, Ptr<const Packet> packet, uint16_t protocol,
|
||||
Address const &source, Address const &destination, NetDevice::PacketType packetType);
|
||||
|
||||
void SendOnePacket (NetDeviceContainer devices, Ipv6Address from, Ipv6Address to);
|
||||
|
||||
NetDeviceContainer m_mockDevices; //!< MockNetDevice container
|
||||
NetDeviceContainer m_sixDevices; //!< SixLowPanNetDevice container
|
||||
|
||||
public:
|
||||
virtual void DoRun (void);
|
||||
SixlowpanIphcStatefulImplTest ();
|
||||
};
|
||||
|
||||
SixlowpanIphcStatefulImplTest::SixlowpanIphcStatefulImplTest ()
|
||||
: TestCase ("Sixlowpan IPHC stateful implementation")
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
SixlowpanIphcStatefulImplTest::ReceiveFromMockDevice (Ptr<NetDevice> device, Ptr<const Packet> packet, uint16_t protocol,
|
||||
Address const &source, Address const &destination, NetDevice::PacketType packetType)
|
||||
{
|
||||
Data incomingPkt;
|
||||
incomingPkt.packet = packet->Copy ();
|
||||
incomingPkt.src = source;
|
||||
incomingPkt.dst = destination;
|
||||
m_txPackets.push_back (incomingPkt);
|
||||
|
||||
Ptr<MockNetDevice> mockDev = DynamicCast<MockNetDevice> (m_mockDevices.Get(1));
|
||||
if (mockDev)
|
||||
{
|
||||
uint32_t id = mockDev->GetNode ()->GetId ();
|
||||
Simulator::ScheduleWithContext (id, Time(1), &MockNetDevice::Receive, mockDev, incomingPkt.packet, protocol, destination, source, packetType);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
SixlowpanIphcStatefulImplTest::PromiscReceiveFromSixLowPanDevice (Ptr<NetDevice> device, Ptr<const Packet> packet, uint16_t protocol,
|
||||
Address const &source, Address const &destination, NetDevice::PacketType packetType)
|
||||
{
|
||||
Data incomingPkt;
|
||||
incomingPkt.packet = packet->Copy ();
|
||||
incomingPkt.src = source;
|
||||
incomingPkt.dst = destination;
|
||||
m_rxPackets.push_back (incomingPkt);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
SixlowpanIphcStatefulImplTest::SendOnePacket (NetDeviceContainer devices, Ipv6Address from, Ipv6Address to)
|
||||
{
|
||||
Ptr<Packet> pkt = Create<Packet> (10);
|
||||
Ipv6Header ipHdr;
|
||||
ipHdr.SetSourceAddress (from);
|
||||
ipHdr.SetDestinationAddress (to);
|
||||
ipHdr.SetHopLimit (64);
|
||||
ipHdr.SetPayloadLength (10);
|
||||
ipHdr.SetNextHeader (0xff);
|
||||
pkt->AddHeader (ipHdr);
|
||||
|
||||
devices.Get (0)->Send (pkt, Mac48Address ("00:00:00:00:00:02"), 0);
|
||||
}
|
||||
|
||||
void
|
||||
SixlowpanIphcStatefulImplTest::DoRun (void)
|
||||
{
|
||||
NodeContainer nodes;
|
||||
nodes.Create(2);
|
||||
|
||||
// First node, setup NetDevices.
|
||||
Ptr<MockNetDevice> mockNetDevice0 = CreateObject<MockNetDevice> ();
|
||||
nodes.Get (0)->AddDevice (mockNetDevice0);
|
||||
mockNetDevice0->SetNode (nodes.Get (0));
|
||||
mockNetDevice0->SetAddress (Mac48Address ("00:00:00:00:00:01"));
|
||||
mockNetDevice0->SetMtu (150);
|
||||
mockNetDevice0->SetSendCallback ( MakeCallback (&SixlowpanIphcStatefulImplTest::ReceiveFromMockDevice, this) );
|
||||
m_mockDevices.Add (mockNetDevice0);
|
||||
|
||||
// Second node, setup NetDevices.
|
||||
Ptr<MockNetDevice> mockNetDevice1 = CreateObject<MockNetDevice> ();
|
||||
nodes.Get (1)->AddDevice (mockNetDevice1);
|
||||
mockNetDevice1->SetNode (nodes.Get (1));
|
||||
mockNetDevice1->SetAddress (Mac48Address ("00:00:00:00:00:02"));
|
||||
mockNetDevice1->SetMtu (150);
|
||||
m_mockDevices.Add (mockNetDevice1);
|
||||
|
||||
InternetStackHelper internetv6;
|
||||
internetv6.Install (nodes);
|
||||
|
||||
SixLowPanHelper sixlowpan;
|
||||
m_sixDevices = sixlowpan.Install (m_mockDevices);
|
||||
m_sixDevices.Get (1)->SetPromiscReceiveCallback ( MakeCallback (&SixlowpanIphcStatefulImplTest::PromiscReceiveFromSixLowPanDevice, this) );
|
||||
|
||||
Ipv6AddressHelper ipv6;
|
||||
ipv6.SetBase (Ipv6Address ("2001:2::"), Ipv6Prefix (64));
|
||||
Ipv6InterfaceContainer deviceInterfaces;
|
||||
deviceInterfaces = ipv6.Assign (m_sixDevices);
|
||||
|
||||
// This is a hack to prevent Router Solicitations and Duplicate Address Detection being sent.
|
||||
for (auto i = nodes.Begin (); i != nodes.End (); i++)
|
||||
{
|
||||
Ptr<Node> node = *i;
|
||||
Ptr<Ipv6L3Protocol> ipv6L3 = (*i)->GetObject<Ipv6L3Protocol> ();
|
||||
if (ipv6L3)
|
||||
{
|
||||
ipv6L3->SetAttribute ("IpForward", BooleanValue (true));
|
||||
ipv6L3->SetAttribute ("SendIcmpv6Redirect", BooleanValue (false));
|
||||
}
|
||||
Ptr<Icmpv6L4Protocol> icmpv6 = (*i)->GetObject<Icmpv6L4Protocol> ();
|
||||
if (icmpv6)
|
||||
{
|
||||
icmpv6->SetAttribute ("DAD", BooleanValue (false));
|
||||
}
|
||||
}
|
||||
|
||||
sixlowpan.AddContext (m_sixDevices, 0, Ipv6Prefix ("2001:2::", 64), Time (Minutes (30)));
|
||||
sixlowpan.AddContext (m_sixDevices, 1, Ipv6Prefix ("2001:1::", 64), Time (Minutes (30)));
|
||||
|
||||
Ipv6Address srcElided = deviceInterfaces.GetAddress (0, 1);
|
||||
Ipv6Address dstElided = Ipv6Address::MakeAutoconfiguredAddress (Mac48Address ("00:00:00:00:00:02"), Ipv6Prefix ("2001:2::", 64));
|
||||
|
||||
Simulator::Schedule (Seconds (1), &SixlowpanIphcStatefulImplTest::SendOnePacket, this, m_sixDevices,
|
||||
Ipv6Address::GetAny (),
|
||||
dstElided);
|
||||
|
||||
Simulator::Schedule (Seconds (2), &SixlowpanIphcStatefulImplTest::SendOnePacket, this, m_sixDevices,
|
||||
Ipv6Address ("2001:2::f00d:f00d:cafe:cafe"),
|
||||
Ipv6Address ("2001:1::0000:00ff:fe00:cafe"));
|
||||
|
||||
Simulator::Schedule (Seconds (3), &SixlowpanIphcStatefulImplTest::SendOnePacket, this, m_sixDevices,
|
||||
Ipv6Address ("2001:1::0000:00ff:fe00:cafe"),
|
||||
Ipv6Address ("2001:1::f00d:f00d:cafe:cafe"));
|
||||
|
||||
Simulator::Schedule (Seconds (4), &SixlowpanIphcStatefulImplTest::SendOnePacket, this, m_sixDevices,
|
||||
srcElided,
|
||||
Ipv6Address ("2001:1::f00d:f00d:cafe:cafe"));
|
||||
|
||||
Simulator::Stop (Seconds (10));
|
||||
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
|
||||
// ------ Now the tests ------------
|
||||
|
||||
SixLowPanIphc iphcHdr;
|
||||
Ipv6Header ipv6Hdr;
|
||||
|
||||
// first packet sent, expected CID(0) SAC(1) SAM (0) M(0) DAC(1) DAM (3)
|
||||
m_txPackets[0].packet->RemoveHeader (iphcHdr);
|
||||
NS_TEST_EXPECT_MSG_EQ (iphcHdr.GetCid (), false, "CID should be false, is true");
|
||||
NS_TEST_EXPECT_MSG_EQ (iphcHdr.GetSac (), true, "SAC should be true, is false");
|
||||
NS_TEST_EXPECT_MSG_EQ (iphcHdr.GetSam (), SixLowPanIphc::HC_INLINE, "SAM should be HC_INLINE, it is not");
|
||||
NS_TEST_EXPECT_MSG_EQ (iphcHdr.GetM (), false, "M should be false, is true");
|
||||
NS_TEST_EXPECT_MSG_EQ (iphcHdr.GetDac (), true, "DAC should be true, is false");
|
||||
NS_TEST_EXPECT_MSG_EQ (iphcHdr.GetSrcContextId (), 0, "Src context should be 0, it is not");
|
||||
NS_TEST_EXPECT_MSG_EQ (iphcHdr.GetDstContextId (), 0, "Dst context should be 0, it is not");
|
||||
NS_TEST_EXPECT_MSG_EQ (iphcHdr.GetDam (), SixLowPanIphc::HC_COMPR_0, "DAM should be HC_COMPR_0, it is not");
|
||||
|
||||
// first packet received, expected :: -> dstElided
|
||||
m_rxPackets[0].packet->RemoveHeader (ipv6Hdr);
|
||||
NS_TEST_EXPECT_MSG_EQ (ipv6Hdr.GetSourceAddress (), Ipv6Address::GetAny (), "Src address wrongly rebuilt");
|
||||
NS_TEST_EXPECT_MSG_EQ (ipv6Hdr.GetDestinationAddress (), dstElided, "Dst address wrongly rebuilt");
|
||||
|
||||
// second packet sent, expected CID(1) SAC(1) SAM (1) M(0) DAC(1) DAM (2)
|
||||
m_txPackets[1].packet->RemoveHeader (iphcHdr);
|
||||
NS_TEST_EXPECT_MSG_EQ (iphcHdr.GetCid (), true, "CID should be true, is false");
|
||||
NS_TEST_EXPECT_MSG_EQ (iphcHdr.GetSac (), true, "SAC should be true, is false");
|
||||
NS_TEST_EXPECT_MSG_EQ (iphcHdr.GetSam (), SixLowPanIphc::HC_COMPR_64, "SAM should be HC_COMPR_64, it is not");
|
||||
NS_TEST_EXPECT_MSG_EQ (iphcHdr.GetM (), false, "M should be false, is true");
|
||||
NS_TEST_EXPECT_MSG_EQ (iphcHdr.GetDac (), true, "DAC should be true, is false");
|
||||
NS_TEST_EXPECT_MSG_EQ (iphcHdr.GetSrcContextId (), 0, "Src context should be 0, it is not");
|
||||
NS_TEST_EXPECT_MSG_EQ (iphcHdr.GetDstContextId (), 1, "Dst context should be 1, it is not");
|
||||
NS_TEST_EXPECT_MSG_EQ (iphcHdr.GetDam (), SixLowPanIphc::HC_COMPR_16, "DAM should be HC_COMPR_16, it is not");
|
||||
|
||||
// second packet received, expected 2001:2::f00d:f00d:cafe:cafe -> 2001:1::0000:00ff:fe00:cafe
|
||||
m_rxPackets[1].packet->RemoveHeader (ipv6Hdr);
|
||||
NS_TEST_EXPECT_MSG_EQ (ipv6Hdr.GetSourceAddress (), Ipv6Address ("2001:2::f00d:f00d:cafe:cafe"), "Src address wrongly rebuilt");
|
||||
NS_TEST_EXPECT_MSG_EQ (ipv6Hdr.GetDestinationAddress (), Ipv6Address ("2001:1::0000:00ff:fe00:cafe"), "Dst address wrongly rebuilt");
|
||||
|
||||
// third packet sent, expected CID(17) SAC(1) SAM (2) M(0) DAC(1) DAM (1)
|
||||
m_txPackets[2].packet->RemoveHeader (iphcHdr);
|
||||
NS_TEST_EXPECT_MSG_EQ (iphcHdr.GetCid (), true, "CID should be true, is false");
|
||||
NS_TEST_EXPECT_MSG_EQ (iphcHdr.GetSac (), true, "SAC should be true, is false");
|
||||
NS_TEST_EXPECT_MSG_EQ (iphcHdr.GetSam (), SixLowPanIphc::HC_COMPR_16, "SAM should be HC_COMPR_16, it is not");
|
||||
NS_TEST_EXPECT_MSG_EQ (iphcHdr.GetM (), false, "M should be false, is true");
|
||||
NS_TEST_EXPECT_MSG_EQ (iphcHdr.GetDac (), true, "DAC should be true, is false");
|
||||
NS_TEST_EXPECT_MSG_EQ (iphcHdr.GetSrcContextId (), 1, "Src context should be 1, it is not");
|
||||
NS_TEST_EXPECT_MSG_EQ (iphcHdr.GetDstContextId (), 1, "Dst context should be 1, it is not");
|
||||
NS_TEST_EXPECT_MSG_EQ (iphcHdr.GetDam (), SixLowPanIphc::HC_COMPR_64, "DAM should be HC_COMPR_64, it is not");
|
||||
|
||||
// third packet received, expected 2001:1::0000:00ff:fe00:cafe -> 2001:1::f00d:f00d:cafe:cafe
|
||||
m_rxPackets[2].packet->RemoveHeader (ipv6Hdr);
|
||||
NS_TEST_EXPECT_MSG_EQ (ipv6Hdr.GetSourceAddress (), Ipv6Address ("2001:1::0000:00ff:fe00:cafe"), "Src address wrongly rebuilt");
|
||||
NS_TEST_EXPECT_MSG_EQ (ipv6Hdr.GetDestinationAddress (), Ipv6Address ("2001:1::f00d:f00d:cafe:cafe"), "Dst address wrongly rebuilt");
|
||||
|
||||
// fourth packet sent, expected CID(1) SAC(1) SAM (3) M(0) DAC(1) DAM (1)
|
||||
m_txPackets[3].packet->RemoveHeader (iphcHdr);
|
||||
NS_TEST_EXPECT_MSG_EQ (iphcHdr.GetCid (), true, "CID should be true, is false");
|
||||
NS_TEST_EXPECT_MSG_EQ (iphcHdr.GetSac (), true, "SAC should be true, is false");
|
||||
NS_TEST_EXPECT_MSG_EQ (iphcHdr.GetSam (), SixLowPanIphc::HC_COMPR_0, "SAM should be HC_COMPR_0, it is not");
|
||||
NS_TEST_EXPECT_MSG_EQ (iphcHdr.GetM (), false, "M should be false, is true");
|
||||
NS_TEST_EXPECT_MSG_EQ (iphcHdr.GetDac (), true, "DAC should be true, is false");
|
||||
NS_TEST_EXPECT_MSG_EQ (iphcHdr.GetSrcContextId (), 0, "Src context should be 0, it is not");
|
||||
NS_TEST_EXPECT_MSG_EQ (iphcHdr.GetDstContextId (), 1, "Dst context should be 1, it is not");
|
||||
NS_TEST_EXPECT_MSG_EQ (iphcHdr.GetDam (), SixLowPanIphc::HC_COMPR_64, "DAM should be HC_COMPR_64, it is not");
|
||||
|
||||
// fourth packet received, expected srcElided -> 2001:1::f00d:f00d:cafe:cafe
|
||||
m_rxPackets[3].packet->RemoveHeader (ipv6Hdr);
|
||||
NS_TEST_EXPECT_MSG_EQ (ipv6Hdr.GetSourceAddress (), srcElided, "Src address wrongly rebuilt");
|
||||
NS_TEST_EXPECT_MSG_EQ (ipv6Hdr.GetDestinationAddress (), Ipv6Address ("2001:1::f00d:f00d:cafe:cafe"), "Dst address wrongly rebuilt");
|
||||
|
||||
m_rxPackets.clear ();
|
||||
m_txPackets.clear ();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \ingroup sixlowpan-test
|
||||
* \ingroup tests
|
||||
*
|
||||
* \brief 6LoWPAN IPHC TestSuite
|
||||
*/
|
||||
class SixlowpanIphcStatefulTestSuite : public TestSuite
|
||||
{
|
||||
public:
|
||||
SixlowpanIphcStatefulTestSuite ();
|
||||
private:
|
||||
};
|
||||
|
||||
SixlowpanIphcStatefulTestSuite::SixlowpanIphcStatefulTestSuite ()
|
||||
: TestSuite ("sixlowpan-iphc-stateful", UNIT)
|
||||
{
|
||||
AddTestCase (new SixlowpanIphcStatefulImplTest (), TestCase::QUICK);
|
||||
}
|
||||
|
||||
static SixlowpanIphcStatefulTestSuite g_sixlowpanIphcStatefulTestSuite; //!< Static variable for test initialization
|
||||
@@ -11,8 +11,10 @@ def build(bld):
|
||||
|
||||
module_test = bld.create_ns3_module_test_library('sixlowpan')
|
||||
module_test.source = [
|
||||
'test/mock-net-device.cc',
|
||||
'test/sixlowpan-hc1-test.cc',
|
||||
'test/sixlowpan-iphc-test.cc',
|
||||
'test/sixlowpan-iphc-stateful-test.cc',
|
||||
'test/sixlowpan-fragmentation-test.cc',
|
||||
]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user