otAddUnicastAddress Doesn't Hold onto External Pointers (#504)

* Modify ot*UnicastAddress functions to use internal memory instead of holding onto an external memory address.
This commit is contained in:
Nick Banks
2016-09-02 16:17:08 -07:00
committed by Jonathan Hui
parent 73060ae8e1
commit 511ade5293
9 changed files with 190 additions and 107 deletions
+11 -10
View File
@@ -651,26 +651,27 @@ const otNetifAddress *otGetUnicastAddresses(void);
/**
* Add a Network Interface Address to the Thread interface.
*
* The passed in instance @p aAddress will be added and stored by the Thread interface, so the caller should ensure
* that the address instance remains valid (not de-alloacted) and is not modified after a successful call to this
* method.
* The passed in instance @p aAddress will be copied by the Thread interface. The Thread interface only
* supports a fixed number of externally added unicast addresses. See OPENTHREAD_CONFIG_MAX_EXT_IP_ADDRS.
*
* @param[in] aAddress A pointer to a Network Interface Address.
*
* @retval kThreadErrorNone Successfully added the Network Interface Address.
* @retval kThreadErrorBusy The Network Interface Address pointed to by @p aAddress is already added.
* @retval kThreadErrorNone Successfully added (or updated) the Network Interface Address.
* @retval kThreadError_InvalidArgs The IP Address indicated by @p aAddress is an internal address.
* @retval kThreadError_NoBufs The Network Interface is already storing the maximum allowed external addresses.
*/
ThreadError otAddUnicastAddress(otNetifAddress *aAddress);
ThreadError otAddUnicastAddress(const otNetifAddress *aAddress);
/**
* Remove a Network Interface Address from the Thread interface.
*
* @param[in] aAddress A pointer to a Network Interface Address.
* @param[in] aAddress A pointer to an IP Address.
*
* @retval kThreadErrorNone Successfully removed the Network Interface Address.
* @retval kThreadErrorNotFound The Network Interface Address point to by @p aAddress was not added.
* @retval kThreadErrorNone Successfully removed the Network Interface Address.
* @retval kThreadError_InvalidArgs The IP Address indicated by @p aAddress is an internal address.
* @retval kThreadError_NotFound The IP Address indicated by @p aAddress was not found.
*/
ThreadError otRemoveUnicastAddress(otNetifAddress *aAddress);
ThreadError otRemoveUnicastAddress(const otIp6Address *aAddress);
/**
* This function pointer is called to notify certain configuration or state changes within OpenThread.
+8 -10
View File
@@ -102,8 +102,6 @@ const struct Command Interpreter::sCommands[] =
#endif
};
otNetifAddress Interpreter::sAddress;
static otDEFINE_ALIGNED_VAR(sPingTimerBuf, sizeof(Timer), uint64_t);
Timer *Interpreter::sPingTimer;
@@ -611,14 +609,15 @@ exit:
ThreadError Interpreter::ProcessIpAddrAdd(int argc, char *argv[])
{
ThreadError error;
otNetifAddress aAddress;
VerifyOrExit(argc > 0, error = kThreadError_Parse);
SuccessOrExit(error = otIp6AddressFromString(argv[0], &sAddress.mAddress));
sAddress.mPrefixLength = 64;
sAddress.mPreferredLifetime = 0xffffffff;
sAddress.mValidLifetime = 0xffffffff;
error = otAddUnicastAddress(&sAddress);
SuccessOrExit(error = otIp6AddressFromString(argv[0], &aAddress.mAddress));
aAddress.mPrefixLength = 64;
aAddress.mPreferredLifetime = 0xffffffff;
aAddress.mValidLifetime = 0xffffffff;
error = otAddUnicastAddress(&aAddress);
exit:
return error;
@@ -632,8 +631,7 @@ ThreadError Interpreter::ProcessIpAddrDel(int argc, char *argv[])
VerifyOrExit(argc > 0, error = kThreadError_Parse);
SuccessOrExit(error = otIp6AddressFromString(argv[0], &address));
VerifyOrExit(otIsIp6AddressEqual(&address, &sAddress.mAddress), error = kThreadError_Parse);
error = otRemoveUnicastAddress(&sAddress);
error = otRemoveUnicastAddress(&address);
exit:
return error;
@@ -1989,7 +1987,7 @@ void Interpreter::HandleNetifStateChanged(uint32_t aFlags, void *aContext)
if (!found)
{
otRemoveUnicastAddress(address);
otRemoveUnicastAddress(&address->mAddress);
address->mValidLifetime = 0;
}
}
-1
View File
@@ -192,7 +192,6 @@ private:
static void HandleLinkPcapReceive(const RadioPacket *aFrame, void *aContext);
static const struct Command sCommands[];
static otNetifAddress sAddress;
static Ip6::MessageInfo sMessageInfo;
static Server *sServer;
+92 -1
View File
@@ -51,6 +51,7 @@ Netif::Netif() :
mInterfaceId = -1;
mAllRoutersSubscribed = false;
mNext = NULL;
mMaskExtUnicastAddresses = 0;
mStateChangedFlags = 0;
}
@@ -313,7 +314,7 @@ ThreadError Netif::RemoveUnicastAddress(const NetifUnicastAddress &aAddress)
}
}
ExitNow(error = kThreadError_Error);
ExitNow(error = kThreadError_NotFound);
exit:
@@ -325,6 +326,96 @@ exit:
return error;
}
ThreadError Netif::AddExternalUnicastAddress(const NetifUnicastAddress &aAddress)
{
ThreadError error = kThreadError_None;
int8_t index = 0;
for (NetifUnicastAddress *cur = mUnicastAddresses; cur; cur = cur->GetNext())
{
if (memcmp(&cur->mAddress, &aAddress.mAddress, sizeof(otIp6Address)) == 0)
{
VerifyOrExit(GetExtUnicastAddressIndex(cur) != -1, error = kThreadError_InvalidArgs);
cur->mPreferredLifetime = aAddress.mPreferredLifetime;
cur->mValidLifetime = aAddress.mValidLifetime;
cur->mPrefixLength = aAddress.mPrefixLength;
ExitNow();
}
}
// Make sure we haven't set all the bits in the mask already
VerifyOrExit(mMaskExtUnicastAddresses != ((1 << OPENTHREAD_CONFIG_MAX_EXT_IP_ADDRS) - 1),
error = kThreadError_NoBufs);
// Get next available entry index
while ((mMaskExtUnicastAddresses & (1 << index)) != 0)
{
index++;
}
assert(index < OPENTHREAD_CONFIG_MAX_EXT_IP_ADDRS);
// Increase the count and mask the index
mMaskExtUnicastAddresses |= 1 << index;
// Copy the address to the next available dynamic address
mExtUnicastAddresses[index] = aAddress;
mExtUnicastAddresses[index].mNext = mUnicastAddresses;
mUnicastAddresses = &mExtUnicastAddresses[index];
SetStateChangedFlags(OT_IP6_ADDRESS_ADDED);
exit:
return error;
}
ThreadError Netif::RemoveExternalUnicastAddress(const Address &aAddress)
{
ThreadError error = kThreadError_None;
NetifUnicastAddress *last = NULL;
int8_t aAddressIndexToRemove = -1;
for (NetifUnicastAddress *cur = mUnicastAddresses; cur; cur = cur->GetNext())
{
if (memcmp(&cur->mAddress, &aAddress, sizeof(otIp6Address)) == 0)
{
aAddressIndexToRemove = GetExtUnicastAddressIndex(cur);
VerifyOrExit(aAddressIndexToRemove != -1, error = kThreadError_InvalidArgs);
if (last)
{
last->mNext = cur->mNext;
}
else
{
mUnicastAddresses = cur->GetNext();
}
break;
}
last = cur;
}
if (aAddressIndexToRemove != -1)
{
mMaskExtUnicastAddresses &= ~(1 << aAddressIndexToRemove);
SetStateChangedFlags(OT_IP6_ADDRESS_REMOVED);
}
else
{
error = kThreadError_NotFound;
}
exit:
return error;
}
Netif *Netif::GetNetifList()
{
return sNetifListHead;
+47 -2
View File
@@ -256,12 +256,36 @@ public:
*
* @param[in] aAddress A reference to the unicast address.
*
* @retval kThreadError_None Successfully removed the unicast address.
* @retval kThreadError_Busy The unicast address was already removed.
* @retval kThreadError_None Successfully removed the unicast address.
* @retval kThreadError_NotFound The unicast address wasn't found to be removed.
*
*/
ThreadError RemoveUnicastAddress(const NetifUnicastAddress &aAddress);
/**
* This method adds an external (to OpenThread) unicast address to the network interface.
*
* @param[in] aAddress A reference to the unicast address.
*
* @retval kThreadError_None Successfully added (or updated) the unicast address.
* @retval kThreadError_InvalidArgs The address indicated by @p aAddress is an internal address.
* @retval kThreadError_NoBufs The maximum number of allowed external addresses are already added.
*
*/
ThreadError AddExternalUnicastAddress(const NetifUnicastAddress &aAddress);
/**
* This method removes a external (to OpenThread) unicast address from the network interface.
*
* @param[in] aAddress A reference to the unicast address.
*
* @retval kThreadError_None Successfully removed the unicast address.
* @retval kThreadError_InvalidArgs The address indicated by @p aAddress is an internal address.
* @retval kThreadError_NotFound The unicast address was not found.
*
*/
ThreadError RemoveExternalUnicastAddress(const Address &aAddress);
/**
* This method indicates whether or not the network interface is subscribed to a multicast address.
*
@@ -450,8 +474,29 @@ private:
uint32_t mStateChangedFlags;
NetifUnicastAddress mExtUnicastAddresses[OPENTHREAD_CONFIG_MAX_EXT_IP_ADDRS];
uint8_t mMaskExtUnicastAddresses; // Must have enough bits to hold OPENTHREAD_CONFIG_MAX_EXT_IP_ADDRS
static Netif *sNetifListHead;
static int8_t sNextInterfaceId;
/**
* This method determines if an address is one of the external unicast addresses, and if so returns
* the index in the mExtUnicastAddresses array.
*
* @param[in] aAddress A pointer to the Network Interface address.
*
* @returns The index in the mExtUnicastAddresses array or -1 if not part of the array.
*
*/
int8_t GetExtUnicastAddressIndex(const NetifUnicastAddress *address) {
if (address < &mExtUnicastAddresses[0] ||
address >= &mExtUnicastAddresses[0] + OPENTHREAD_CONFIG_MAX_EXT_IP_ADDRS) {
return -1;
}
return static_cast<int8_t>(address - &mExtUnicastAddresses[0]);
}
};
/**
+10
View File
@@ -115,6 +115,16 @@
#define OPENTHREAD_CONFIG_IP_ADDRS_PER_CHILD 4
#endif // OPENTHREAD_CONFIG_IP_ADDRS_PER_CHILD
/**
* @def OPENTHREAD_CONFIG_MAX_EXT_IP_ADDRS
*
* The maximum number of supported IPv6 addresses allows to be externally added.
*
*/
#ifndef OPENTHREAD_CONFIG_MAX_EXT_IP_ADDRS
#define OPENTHREAD_CONFIG_MAX_EXT_IP_ADDRS 4
#endif // OPENTHREAD_CONFIG_MAX_EXT_IP_ADDRS
/**
* @def OPENTHREAD_CONFIG_6LOWPAN_REASSEMBLY_TIMEOUT
*
+4 -4
View File
@@ -824,14 +824,14 @@ const otNetifAddress *otGetUnicastAddresses(void)
return sThreadNetif->GetUnicastAddresses();
}
ThreadError otAddUnicastAddress(otNetifAddress *address)
ThreadError otAddUnicastAddress(const otNetifAddress *address)
{
return sThreadNetif->AddUnicastAddress(*static_cast<Ip6::NetifUnicastAddress *>(address));
return sThreadNetif->AddExternalUnicastAddress(*static_cast<const Ip6::NetifUnicastAddress *>(address));
}
ThreadError otRemoveUnicastAddress(otNetifAddress *address)
ThreadError otRemoveUnicastAddress(const otIp6Address *address)
{
return sThreadNetif->RemoveUnicastAddress(*static_cast<Ip6::NetifUnicastAddress *>(address));
return sThreadNetif->RemoveExternalUnicastAddress(*static_cast<const Ip6::Address *>(address));
}
void otSetStateChangedCallback(otStateChangedCallback aCallback, void *aContext)
+18 -72
View File
@@ -426,11 +426,6 @@ NcpBase::NcpBase():
mDroppedOutboundIpFrameCounter = 0;
mDroppedInboundIpFrameCounter = 0;
for (unsigned i = 0; i < sizeof(mNetifAddresses) / sizeof(mNetifAddresses[0]); i++)
{
mNetifAddresses[i].mPrefixLength = kUnusedNetifAddressPrefixLen;
}
assert(sThreadNetif != NULL);
otSetStateChangedCallback(&HandleNetifStateChanged, this);
otSetReceiveIp6DatagramCallback(&HandleDatagramFromStack, this);
@@ -3785,7 +3780,7 @@ ThreadError NcpBase::InsertPropertyHandler_IPV6_ADDRESS_TABLE(uint8_t header, sp
spinel_ssize_t parsedLength;
ThreadError errorCode = kThreadError_None;
spinel_status_t errorStatus = SPINEL_STATUS_OK;
otNetifAddress *netif_addr = NULL;
otNetifAddress netif_addr;
otIp6Address *addr_ptr;
uint32_t preferred_lifetime;
uint32_t valid_lifetime;
@@ -3803,41 +3798,14 @@ ThreadError NcpBase::InsertPropertyHandler_IPV6_ADDRESS_TABLE(uint8_t header, sp
VerifyOrExit(parsedLength > 0, errorStatus = SPINEL_STATUS_PARSE_ERROR);
VerifyOrExit(prefix_len != kUnusedNetifAddressPrefixLen, errorStatus = SPINEL_STATUS_INVALID_ARGUMENT);
netif_addr.mAddress = *addr_ptr;
netif_addr.mPrefixLength = prefix_len;
netif_addr.mPreferredLifetime = preferred_lifetime;
netif_addr.mValidLifetime = valid_lifetime;
for (unsigned i = 0; i < sizeof(mNetifAddresses) / sizeof(mNetifAddresses[0]); i++)
{
if (mNetifAddresses[i].mPrefixLength != kUnusedNetifAddressPrefixLen)
{
// If the address matches an already added address.
if (memcmp(&mNetifAddresses[i].mAddress, addr_ptr, sizeof(otIp6Address)) == 0)
{
netif_addr = &mNetifAddresses[i];
break;
}
}
else
{
if (netif_addr == NULL)
{
netif_addr = &mNetifAddresses[i];
}
}
}
errorCode = otAddUnicastAddress(&netif_addr);
VerifyOrExit(netif_addr != NULL, errorStatus = SPINEL_STATUS_NOMEM);
netif_addr->mAddress = *addr_ptr;
netif_addr->mPrefixLength = prefix_len;
netif_addr->mPreferredLifetime = preferred_lifetime;
netif_addr->mValidLifetime = valid_lifetime;
errorCode = otAddUnicastAddress(netif_addr);
// `kThreadError_Busy` indicates that the address was already on the list. In this case the lifetimes and prefix len
// are updated, and the add/insert operation is considered a success.
VerifyOrExit(errorCode == kThreadError_None || errorCode == kThreadError_Busy,
VerifyOrExit(errorCode == kThreadError_None,
errorStatus = ThreadErrorToSpinelStatus(errorCode));
errorCode = SendPropertyUpdate(
@@ -4110,7 +4078,6 @@ ThreadError NcpBase::RemovePropertyHandler_IPV6_ADDRESS_TABLE(uint8_t header, sp
{
spinel_ssize_t parsedLength;
ThreadError errorCode = kThreadError_None;
otNetifAddress *netif_addr = NULL;
otIp6Address *addr_ptr;
parsedLength = spinel_datatype_unpack(
@@ -4125,42 +4092,21 @@ ThreadError NcpBase::RemovePropertyHandler_IPV6_ADDRESS_TABLE(uint8_t header, sp
if (parsedLength > 0)
{
for (unsigned i = 0; i < sizeof(mNetifAddresses) / sizeof(mNetifAddresses[0]); i++)
errorCode = otRemoveUnicastAddress(addr_ptr);
if (errorCode == kThreadError_None)
{
if (mNetifAddresses[i].mPrefixLength != kUnusedNetifAddressPrefixLen)
{
if (memcmp(&mNetifAddresses[i].mAddress, addr_ptr, sizeof(otIp6Address)) == 0)
{
netif_addr = &mNetifAddresses[i];
break;
}
}
}
if (netif_addr != NULL)
{
errorCode = otRemoveUnicastAddress(netif_addr);
if (errorCode == kThreadError_None)
{
netif_addr->mNext = NULL;
errorCode = SendPropertyUpdate(
header,
SPINEL_CMD_PROP_VALUE_REMOVED,
key,
value_ptr,
value_len
);
}
else
{
errorCode = SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode));
}
errorCode = SendPropertyUpdate(
header,
SPINEL_CMD_PROP_VALUE_REMOVED,
key,
value_ptr,
value_len
);
}
else
{
errorCode = SendLastStatus(header, ThreadErrorToSpinelStatus(kThreadError_NoAddress));
errorCode = SendLastStatus(header, ThreadErrorToSpinelStatus(errorCode));
}
}
else
-7
View File
@@ -411,11 +411,6 @@ private:
uint16_t value_len);
private:
enum
{
kNetifAddressListSize = 8, // Size of mNetifAddresses array.
kUnusedNetifAddressPrefixLen = 0xff, // Prefix len value to indicate an unused/available NetifAddress element.
};
spinel_status_t mLastStatus;
@@ -435,8 +430,6 @@ private:
uint16_t mDroppedReplyTidBitSet;
otNetifAddress mNetifAddresses[kNetifAddressListSize];
bool mAllowLocalNetworkDataChange;
bool mRequireJoinExistingNetwork;