mirror of
https://github.com/espressif/openthread.git
synced 2026-07-29 07:07:47 +00:00
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:
+11
-10
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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]);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
*
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user