mirror of
https://github.com/espressif/openthread.git
synced 2026-09-14 13:10:08 +00:00
IP: Add API to subscribe/unsubscribe to multicast addresses. (#899)
* IP: Add API to subscribe/unsubscribe to multicast addresses. * CLI: Add commands to handle multicast addresses.
This commit is contained in:
committed by
Jonathan Hui
parent
30c9dfc0bc
commit
bb97cbee17
@@ -841,18 +841,28 @@ typedef struct otMacCounters
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This structure represents an IPv6 network interface address.
|
* This structure represents an IPv6 network interface unicast address.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
typedef struct otNetifAddress
|
typedef struct otNetifAddress
|
||||||
{
|
{
|
||||||
otIp6Address mAddress; ///< The IPv6 address.
|
otIp6Address mAddress; ///< The IPv6 unicast address.
|
||||||
uint32_t mPreferredLifetime; ///< The Preferred Lifetime.
|
uint32_t mPreferredLifetime; ///< The Preferred Lifetime.
|
||||||
uint32_t mValidLifetime; ///< The Valid lifetime.
|
uint32_t mValidLifetime; ///< The Valid lifetime.
|
||||||
uint8_t mPrefixLength; ///< The Prefix length.
|
uint8_t mPrefixLength; ///< The Prefix length.
|
||||||
struct otNetifAddress *mNext; ///< A pointer to the next network interface address.
|
struct otNetifAddress *mNext; ///< A pointer to the next network interface address.
|
||||||
} otNetifAddress;
|
} otNetifAddress;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This structure represents an IPv6 network interface multicast address.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
typedef struct otNetifMulticastAddress
|
||||||
|
{
|
||||||
|
otIp6Address mAddress; ///< The IPv6 multicast address.
|
||||||
|
struct otNetifMulticastAddress *mNext; ///< A pointer to the next network interface multicast address.
|
||||||
|
} otNetifMulticastAddress;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This enumeration represents the list of allowable values for an InterfaceId.
|
* This enumeration represents the list of allowable values for an InterfaceId.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -790,6 +790,72 @@ ThreadError otAddUnicastAddress(otInstance *aInstance, const otNetifAddress *aAd
|
|||||||
*/
|
*/
|
||||||
ThreadError otRemoveUnicastAddress(otInstance *aInstance, const otIp6Address *aAddress);
|
ThreadError otRemoveUnicastAddress(otInstance *aInstance, const otIp6Address *aAddress);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of IPv6 multicast addresses subscribed to the Thread interface.
|
||||||
|
*
|
||||||
|
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||||
|
*
|
||||||
|
* @returns A pointer to the first Network Interface Multicast Address.
|
||||||
|
*/
|
||||||
|
const otNetifMulticastAddress *otGetMulticastAddresses(otInstance *aInstance);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscribe the Thread interface to a Network Interface Multicast Address.
|
||||||
|
*
|
||||||
|
* The passed in instance @p aAddress will be copied by the Thread interface. The Thread interface only
|
||||||
|
* supports a fixed number of externally added multicast addresses. See OPENTHREAD_CONFIG_MAX_EXT_MULTICAST_IP_ADDRS.
|
||||||
|
*
|
||||||
|
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||||
|
* @param[in] aAddress A pointer to an IP Address.
|
||||||
|
*
|
||||||
|
* @retval kThreadErrorNone Successfully subscribed to the Network Interface Multicast Address.
|
||||||
|
* @retval kThreadError_InvalidArgs The IP Address indicated by @p aAddress is invalid address.
|
||||||
|
* @retval kThreadError_NoBufs The Network Interface is already storing the maximum allowed external multicast addresses.
|
||||||
|
*/
|
||||||
|
ThreadError otSubscribeMulticastAddress(otInstance *aInstance, const otIp6Address *aAddress);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unsubscribe the Thread interface to a Network Interface Multicast Address.
|
||||||
|
*
|
||||||
|
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||||
|
* @param[in] aAddress A pointer to an IP Address.
|
||||||
|
*
|
||||||
|
* @retval kThreadErrorNone Successfully unsubscribed to the Network Interface Multicast 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 otUnsubscribeMulticastAddress(otInstance *aInstance, const otIp6Address *aAddress);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if multicast promiscuous mode is enabled on the Thread interface.
|
||||||
|
*
|
||||||
|
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||||
|
*
|
||||||
|
* @sa otEnableMulticastPromiscuousMode
|
||||||
|
* @sa otDisableMulticastPromiscuousMode
|
||||||
|
*/
|
||||||
|
bool otIsMulticastPromiscuousModeEnabled(otInstance *aInstance);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable multicast promiscuous mode on the Thread interface.
|
||||||
|
*
|
||||||
|
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||||
|
*
|
||||||
|
* @sa otIsMulticastPromiscuousModeEnabled
|
||||||
|
* @sa otDisableMulticastPromiscuousMode
|
||||||
|
*/
|
||||||
|
void otEnableMulticastPromiscuousMode(otInstance *aInstance);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable multicast promiscuous mode on the Thread interface.
|
||||||
|
*
|
||||||
|
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||||
|
*
|
||||||
|
* @sa otIsMulticastPromiscuousModeEnabled
|
||||||
|
* @sa otEnableMulticastPromiscuousMode
|
||||||
|
*/
|
||||||
|
void otDisableMulticastPromiscuousMode(otInstance *aInstance);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function pointer is called to create IPv6 IID during SLAAC procedure.
|
* This function pointer is called to create IPv6 IID during SLAAC procedure.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ OpenThread test scripts use the CLI to execute test cases.
|
|||||||
* [hashmacaddr](#hashmacaddr)
|
* [hashmacaddr](#hashmacaddr)
|
||||||
* [ifconfig](#ifconfig)
|
* [ifconfig](#ifconfig)
|
||||||
* [ipaddr](#ipaddr)
|
* [ipaddr](#ipaddr)
|
||||||
|
* [ipmaddr](#ipmaddr)
|
||||||
* [joiner](#joiner)
|
* [joiner](#joiner)
|
||||||
* [keysequence](#keysequence)
|
* [keysequence](#keysequence)
|
||||||
* [leaderpartitionid](#leaderpartitionid)
|
* [leaderpartitionid](#leaderpartitionid)
|
||||||
@@ -789,6 +790,64 @@ Delete an IPv6 address from the Thread interface.
|
|||||||
Done
|
Done
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### ipmaddr
|
||||||
|
|
||||||
|
List all IPv6 multicast addresses subscribed to the Thread interface.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
> ipmaddr
|
||||||
|
ff05:0:0:0:0:0:0:1
|
||||||
|
ff33:40:fdde:ad00:beef:0:0:1
|
||||||
|
ff32:40:fdde:ad00:beef:0:0:1
|
||||||
|
Done
|
||||||
|
```
|
||||||
|
|
||||||
|
### ipmaddr add \<ipaddr\>
|
||||||
|
|
||||||
|
Subscribe the Thread interface to the IPv6 multicast address.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
> ipmaddr add ff05::1
|
||||||
|
Done
|
||||||
|
```
|
||||||
|
|
||||||
|
### ipmaddr del \<ipaddr\>
|
||||||
|
|
||||||
|
Unsubscribe the Thread interface to the IPv6 multicast address.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
> ipmaddr del ff05::1
|
||||||
|
Done
|
||||||
|
```
|
||||||
|
|
||||||
|
### ipmaddr promiscuous
|
||||||
|
|
||||||
|
Get multicast promiscuous mode.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
> ipmaddr promiscuous
|
||||||
|
Disabled
|
||||||
|
Done
|
||||||
|
```
|
||||||
|
|
||||||
|
### ipmaddr promiscuous enable
|
||||||
|
|
||||||
|
Enable multicast promiscuous mode.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
> ipmaddr promiscuous enable
|
||||||
|
Done
|
||||||
|
```
|
||||||
|
|
||||||
|
### ipmaddr promiscuous disable
|
||||||
|
|
||||||
|
Disable multicast promiscuous mode.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
> ipmaddr promiscuous disable
|
||||||
|
Done
|
||||||
|
```
|
||||||
|
|
||||||
### joiner start \<pskd\> \<provisioningUrl\>
|
### joiner start \<pskd\> \<provisioningUrl\>
|
||||||
|
|
||||||
Start the Joiner role.
|
Start the Joiner role.
|
||||||
|
|||||||
+103
@@ -92,6 +92,7 @@ const struct Command Interpreter::sCommands[] =
|
|||||||
{ "hashmacaddr", &Interpreter::ProcessHashMacAddress },
|
{ "hashmacaddr", &Interpreter::ProcessHashMacAddress },
|
||||||
{ "ifconfig", &Interpreter::ProcessIfconfig },
|
{ "ifconfig", &Interpreter::ProcessIfconfig },
|
||||||
{ "ipaddr", &Interpreter::ProcessIpAddr },
|
{ "ipaddr", &Interpreter::ProcessIpAddr },
|
||||||
|
{ "ipmaddr", &Interpreter::ProcessIpMulticastAddr },
|
||||||
#if OPENTHREAD_ENABLE_JOINER
|
#if OPENTHREAD_ENABLE_JOINER
|
||||||
{ "joiner", &Interpreter::ProcessJoiner },
|
{ "joiner", &Interpreter::ProcessJoiner },
|
||||||
#endif
|
#endif
|
||||||
@@ -770,6 +771,108 @@ exit:
|
|||||||
AppendResult(error);
|
AppendResult(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ThreadError Interpreter::ProcessIpMulticastAddrAdd(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
ThreadError error;
|
||||||
|
struct otIp6Address address;
|
||||||
|
|
||||||
|
VerifyOrExit(argc > 0, error = kThreadError_Parse);
|
||||||
|
|
||||||
|
SuccessOrExit(error = otIp6AddressFromString(argv[0], &address));
|
||||||
|
error = otSubscribeMulticastAddress(mInstance, &address);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThreadError Interpreter::ProcessIpMulticastAddrDel(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
ThreadError error;
|
||||||
|
struct otIp6Address address;
|
||||||
|
|
||||||
|
VerifyOrExit(argc > 0, error = kThreadError_Parse);
|
||||||
|
|
||||||
|
SuccessOrExit(error = otIp6AddressFromString(argv[0], &address));
|
||||||
|
error = otUnsubscribeMulticastAddress(mInstance, &address);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThreadError Interpreter::ProcessMulticastPromiscuous(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
ThreadError error = kThreadError_None;
|
||||||
|
|
||||||
|
if (argc == 0)
|
||||||
|
{
|
||||||
|
if (otIsMulticastPromiscuousModeEnabled(mInstance))
|
||||||
|
{
|
||||||
|
sServer->OutputFormat("Enabled\r\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sServer->OutputFormat("Disabled\r\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (strcmp(argv[0], "enable") == 0)
|
||||||
|
{
|
||||||
|
otEnableMulticastPromiscuousMode(mInstance);
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[0], "disable") == 0)
|
||||||
|
{
|
||||||
|
otDisableMulticastPromiscuousMode(mInstance);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ExitNow(error = kThreadError_Parse);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Interpreter::ProcessIpMulticastAddr(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
ThreadError error = kThreadError_None;
|
||||||
|
|
||||||
|
if (argc == 0)
|
||||||
|
{
|
||||||
|
for (const otNetifMulticastAddress *addr = otGetMulticastAddresses(mInstance); addr; addr = addr->mNext)
|
||||||
|
{
|
||||||
|
sServer->OutputFormat("%x:%x:%x:%x:%x:%x:%x:%x\r\n",
|
||||||
|
HostSwap16(addr->mAddress.mFields.m16[0]),
|
||||||
|
HostSwap16(addr->mAddress.mFields.m16[1]),
|
||||||
|
HostSwap16(addr->mAddress.mFields.m16[2]),
|
||||||
|
HostSwap16(addr->mAddress.mFields.m16[3]),
|
||||||
|
HostSwap16(addr->mAddress.mFields.m16[4]),
|
||||||
|
HostSwap16(addr->mAddress.mFields.m16[5]),
|
||||||
|
HostSwap16(addr->mAddress.mFields.m16[6]),
|
||||||
|
HostSwap16(addr->mAddress.mFields.m16[7]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (strcmp(argv[0], "add") == 0)
|
||||||
|
{
|
||||||
|
SuccessOrExit(error = ProcessIpMulticastAddrAdd(argc - 1, argv + 1));
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[0], "del") == 0)
|
||||||
|
{
|
||||||
|
SuccessOrExit(error = ProcessIpMulticastAddrDel(argc - 1, argv + 1));
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[0], "promiscuous") == 0)
|
||||||
|
{
|
||||||
|
SuccessOrExit(error = ProcessMulticastPromiscuous(argc - 1, argv + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
AppendResult(error);
|
||||||
|
}
|
||||||
|
|
||||||
void Interpreter::ProcessKeySequence(int argc, char *argv[])
|
void Interpreter::ProcessKeySequence(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
ThreadError error = kThreadError_None;
|
ThreadError error = kThreadError_None;
|
||||||
|
|||||||
@@ -167,6 +167,10 @@ private:
|
|||||||
void ProcessIpAddr(int argc, char *argv[]);
|
void ProcessIpAddr(int argc, char *argv[]);
|
||||||
ThreadError ProcessIpAddrAdd(int argc, char *argv[]);
|
ThreadError ProcessIpAddrAdd(int argc, char *argv[]);
|
||||||
ThreadError ProcessIpAddrDel(int argc, char *argv[]);
|
ThreadError ProcessIpAddrDel(int argc, char *argv[]);
|
||||||
|
void ProcessIpMulticastAddr(int argc, char *argv[]);
|
||||||
|
ThreadError ProcessIpMulticastAddrAdd(int argc, char *argv[]);
|
||||||
|
ThreadError ProcessIpMulticastAddrDel(int argc, char *argv[]);
|
||||||
|
ThreadError ProcessMulticastPromiscuous(int argc, char *argv[]);
|
||||||
#if OPENTHREAD_ENABLE_JOINER
|
#if OPENTHREAD_ENABLE_JOINER
|
||||||
void ProcessJoiner(int argc, char *argv[]);
|
void ProcessJoiner(int argc, char *argv[]);
|
||||||
#endif // OPENTHREAD_ENABLE_JOINER
|
#endif // OPENTHREAD_ENABLE_JOINER
|
||||||
|
|||||||
+14
-2
@@ -645,6 +645,7 @@ ThreadError Ip6::HandleDatagram(Message &message, Netif *netif, int8_t interface
|
|||||||
bool receive = false;
|
bool receive = false;
|
||||||
bool forward = false;
|
bool forward = false;
|
||||||
bool tunnel = false;
|
bool tunnel = false;
|
||||||
|
bool multicastPromiscuous = false;
|
||||||
uint8_t nextHeader;
|
uint8_t nextHeader;
|
||||||
uint8_t hopLimit;
|
uint8_t hopLimit;
|
||||||
|
|
||||||
@@ -677,9 +678,16 @@ ThreadError Ip6::HandleDatagram(Message &message, Netif *netif, int8_t interface
|
|||||||
// determine destination of packet
|
// determine destination of packet
|
||||||
if (header.GetDestination().IsMulticast())
|
if (header.GetDestination().IsMulticast())
|
||||||
{
|
{
|
||||||
if (netif != NULL && netif->IsMulticastSubscribed(header.GetDestination()))
|
if (netif != NULL)
|
||||||
{
|
{
|
||||||
receive = true;
|
if (netif->IsMulticastSubscribed(header.GetDestination()))
|
||||||
|
{
|
||||||
|
receive = true;
|
||||||
|
}
|
||||||
|
else if (netif->IsMulticastPromiscuousModeEnabled())
|
||||||
|
{
|
||||||
|
multicastPromiscuous = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (netif == NULL)
|
if (netif == NULL)
|
||||||
@@ -739,6 +747,10 @@ ThreadError Ip6::HandleDatagram(Message &message, Netif *netif, int8_t interface
|
|||||||
|
|
||||||
SuccessOrExit(error = HandlePayload(message, messageInfo, nextHeader));
|
SuccessOrExit(error = HandlePayload(message, messageInfo, nextHeader));
|
||||||
}
|
}
|
||||||
|
else if (multicastPromiscuous)
|
||||||
|
{
|
||||||
|
ProcessReceiveCallback(message, messageInfo, nextHeader);
|
||||||
|
}
|
||||||
|
|
||||||
if (forward)
|
if (forward)
|
||||||
{
|
{
|
||||||
|
|||||||
+116
-14
@@ -42,17 +42,18 @@ namespace Ip6 {
|
|||||||
|
|
||||||
Netif::Netif(Ip6 &aIp6, int8_t aInterfaceId):
|
Netif::Netif(Ip6 &aIp6, int8_t aInterfaceId):
|
||||||
mIp6(aIp6),
|
mIp6(aIp6),
|
||||||
mStateChangedTask(aIp6.mTaskletScheduler, &Netif::HandleStateChangedTask, this)
|
mCallbacks(NULL),
|
||||||
|
mUnicastAddresses(NULL),
|
||||||
|
mMulticastAddresses(NULL),
|
||||||
|
mInterfaceId(aInterfaceId),
|
||||||
|
mAllRoutersSubscribed(false),
|
||||||
|
mMulticastPromiscuousMode(false),
|
||||||
|
mStateChangedTask(aIp6.mTaskletScheduler, &Netif::HandleStateChangedTask, this),
|
||||||
|
mNext(NULL),
|
||||||
|
mStateChangedFlags(0),
|
||||||
|
mMaskExtUnicastAddresses(0),
|
||||||
|
mMaskExtMulticastAddresses(0)
|
||||||
{
|
{
|
||||||
mCallbacks = NULL;
|
|
||||||
mUnicastAddresses = NULL;
|
|
||||||
mMulticastAddresses = NULL;
|
|
||||||
mInterfaceId = aInterfaceId;
|
|
||||||
mAllRoutersSubscribed = false;
|
|
||||||
mNext = NULL;
|
|
||||||
mMaskExtUnicastAddresses = 0;
|
|
||||||
|
|
||||||
mStateChangedFlags = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ThreadError Netif::RegisterCallback(NetifCallback &aCallback)
|
ThreadError Netif::RegisterCallback(NetifCallback &aCallback)
|
||||||
@@ -132,7 +133,7 @@ bool Netif::IsMulticastSubscribed(const Address &aAddress) const
|
|||||||
ExitNow(rval = mAllRoutersSubscribed);
|
ExitNow(rval = mAllRoutersSubscribed);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (NetifMulticastAddress *cur = mMulticastAddresses; cur; cur = cur->mNext)
|
for (NetifMulticastAddress *cur = mMulticastAddresses; cur; cur = cur->GetNext())
|
||||||
{
|
{
|
||||||
if (memcmp(&cur->mAddress, &aAddress, sizeof(cur->mAddress)) == 0)
|
if (memcmp(&cur->mAddress, &aAddress, sizeof(cur->mAddress)) == 0)
|
||||||
{
|
{
|
||||||
@@ -154,11 +155,16 @@ void Netif::UnsubscribeAllRoutersMulticast()
|
|||||||
mAllRoutersSubscribed = false;
|
mAllRoutersSubscribed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const NetifMulticastAddress *Netif::GetMulticastAddresses() const
|
||||||
|
{
|
||||||
|
return mMulticastAddresses;
|
||||||
|
}
|
||||||
|
|
||||||
ThreadError Netif::SubscribeMulticast(NetifMulticastAddress &aAddress)
|
ThreadError Netif::SubscribeMulticast(NetifMulticastAddress &aAddress)
|
||||||
{
|
{
|
||||||
ThreadError error = kThreadError_None;
|
ThreadError error = kThreadError_None;
|
||||||
|
|
||||||
for (NetifMulticastAddress *cur = mMulticastAddresses; cur; cur = cur->mNext)
|
for (NetifMulticastAddress *cur = mMulticastAddresses; cur; cur = cur->GetNext())
|
||||||
{
|
{
|
||||||
if (cur == &aAddress)
|
if (cur == &aAddress)
|
||||||
{
|
{
|
||||||
@@ -179,12 +185,12 @@ ThreadError Netif::UnsubscribeMulticast(const NetifMulticastAddress &aAddress)
|
|||||||
|
|
||||||
if (mMulticastAddresses == &aAddress)
|
if (mMulticastAddresses == &aAddress)
|
||||||
{
|
{
|
||||||
mMulticastAddresses = mMulticastAddresses->mNext;
|
mMulticastAddresses = mMulticastAddresses->GetNext();
|
||||||
ExitNow();
|
ExitNow();
|
||||||
}
|
}
|
||||||
else if (mMulticastAddresses != NULL)
|
else if (mMulticastAddresses != NULL)
|
||||||
{
|
{
|
||||||
for (NetifMulticastAddress *cur = mMulticastAddresses; cur->mNext; cur = cur->mNext)
|
for (NetifMulticastAddress *cur = mMulticastAddresses; cur->GetNext(); cur = cur->GetNext())
|
||||||
{
|
{
|
||||||
if (cur->mNext == &aAddress)
|
if (cur->mNext == &aAddress)
|
||||||
{
|
{
|
||||||
@@ -200,6 +206,102 @@ exit:
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ThreadError Netif::SubscribeExternalMulticast(const Address &aAddress)
|
||||||
|
{
|
||||||
|
ThreadError error = kThreadError_None;
|
||||||
|
int8_t index = 0;
|
||||||
|
|
||||||
|
for (NetifMulticastAddress *cur = mMulticastAddresses; cur; cur = cur->GetNext())
|
||||||
|
{
|
||||||
|
if (memcmp(&cur->mAddress, &aAddress, sizeof(otIp6Address)) == 0)
|
||||||
|
{
|
||||||
|
VerifyOrExit(GetExtMulticastAddressIndex(cur) != -1, error = kThreadError_InvalidArgs);
|
||||||
|
ExitNow(error = kThreadError_Already);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure we haven't set all the bits in the mask already
|
||||||
|
VerifyOrExit(mMaskExtMulticastAddresses != ((1 << OPENTHREAD_CONFIG_MAX_EXT_MULTICAST_IP_ADDRS) - 1),
|
||||||
|
error = kThreadError_NoBufs);
|
||||||
|
|
||||||
|
// Get next available entry index
|
||||||
|
while ((mMaskExtMulticastAddresses & (1 << index)) != 0)
|
||||||
|
{
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(index < OPENTHREAD_CONFIG_MAX_EXT_MULTICAST_IP_ADDRS);
|
||||||
|
|
||||||
|
// Increase the count and mask the index
|
||||||
|
mMaskExtMulticastAddresses |= 1 << index;
|
||||||
|
|
||||||
|
// Copy the address to the next available dynamic address
|
||||||
|
mExtMulticastAddresses[index].mAddress = aAddress;
|
||||||
|
mExtMulticastAddresses[index].mNext = mMulticastAddresses;
|
||||||
|
|
||||||
|
mMulticastAddresses = &mExtMulticastAddresses[index];
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThreadError Netif::UnsubscribeExternalMulticast(const Address &aAddress)
|
||||||
|
{
|
||||||
|
ThreadError error = kThreadError_None;
|
||||||
|
NetifMulticastAddress *last = NULL;
|
||||||
|
int8_t aAddressIndexToRemove = -1;
|
||||||
|
|
||||||
|
for (NetifMulticastAddress *cur = mMulticastAddresses; cur; cur = cur->GetNext())
|
||||||
|
{
|
||||||
|
if (memcmp(&cur->mAddress, &aAddress, sizeof(otIp6Address)) == 0)
|
||||||
|
{
|
||||||
|
aAddressIndexToRemove = GetExtMulticastAddressIndex(cur);
|
||||||
|
VerifyOrExit(aAddressIndexToRemove != -1, error = kThreadError_InvalidArgs);
|
||||||
|
|
||||||
|
if (last)
|
||||||
|
{
|
||||||
|
last->mNext = cur->GetNext();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mMulticastAddresses = cur->GetNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
last = cur;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aAddressIndexToRemove != -1)
|
||||||
|
{
|
||||||
|
mMaskExtMulticastAddresses &= ~(1 << aAddressIndexToRemove);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
error = kThreadError_NotFound;
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Netif::IsMulticastPromiscuousModeEnabled(void)
|
||||||
|
{
|
||||||
|
return mMulticastPromiscuousMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Netif::EnableMulticastPromiscuousMode(void)
|
||||||
|
{
|
||||||
|
mMulticastPromiscuousMode = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Netif::DisableMulticastPromiscuousMode(void)
|
||||||
|
{
|
||||||
|
mMulticastPromiscuousMode = false;
|
||||||
|
}
|
||||||
|
|
||||||
const NetifUnicastAddress *Netif::GetUnicastAddresses() const
|
const NetifUnicastAddress *Netif::GetUnicastAddresses() const
|
||||||
{
|
{
|
||||||
return mUnicastAddresses;
|
return mUnicastAddresses;
|
||||||
|
|||||||
+85
-6
@@ -121,7 +121,7 @@ public:
|
|||||||
* This class implements an IPv6 network interface multicast address.
|
* This class implements an IPv6 network interface multicast address.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class NetifMulticastAddress
|
class NetifMulticastAddress: public otNetifMulticastAddress
|
||||||
{
|
{
|
||||||
friend class Netif;
|
friend class Netif;
|
||||||
|
|
||||||
@@ -143,16 +143,20 @@ public:
|
|||||||
Address &GetAddress(void) { return *static_cast<Address *>(&mAddress); }
|
Address &GetAddress(void) { return *static_cast<Address *>(&mAddress); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the next multicast address assigned to the interface.
|
* This method returns the next multicast address subscribed to the interface.
|
||||||
*
|
*
|
||||||
* @returns A pointer to the next multicast address.
|
* @returns A pointer to the next multicast address.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
const NetifMulticastAddress *GetNext(void) const { return mNext; }
|
const NetifMulticastAddress *GetNext(void) const { return static_cast<NetifMulticastAddress *>(mNext); }
|
||||||
|
|
||||||
private:
|
/**
|
||||||
Address mAddress;
|
* This method returns the next multicast address subscribed to the interface.
|
||||||
NetifMulticastAddress *mNext;
|
*
|
||||||
|
* @returns A pointer to the next multicast address.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
NetifMulticastAddress *GetNext(void) { return static_cast<NetifMulticastAddress *>(mNext); }
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -349,6 +353,14 @@ public:
|
|||||||
*/
|
*/
|
||||||
void UnsubscribeAllRoutersMulticast(void);
|
void UnsubscribeAllRoutersMulticast(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method returns a pointer to the list of multicast addresses.
|
||||||
|
*
|
||||||
|
* @returns A pointer to the list of multicast addresses.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
const NetifMulticastAddress *GetMulticastAddresses(void) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method subscribes the network interface to a multicast address.
|
* This method subscribes the network interface to a multicast address.
|
||||||
*
|
*
|
||||||
@@ -371,6 +383,51 @@ public:
|
|||||||
*/
|
*/
|
||||||
ThreadError UnsubscribeMulticast(const NetifMulticastAddress &aAddress);
|
ThreadError UnsubscribeMulticast(const NetifMulticastAddress &aAddress);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method subscribes the network interface to the external (to OpenThread) multicast address.
|
||||||
|
*
|
||||||
|
* @param[in] aAddress A reference to the multicast address.
|
||||||
|
*
|
||||||
|
* @retval kThreadError_None Successfully subscribed to @p aAddress.
|
||||||
|
* @retval kThreadError_Already The multicast address is already subscribed.
|
||||||
|
* @retval kThreadError_InvalidArgs The address indicated by @p aAddress is an internal multicast address.
|
||||||
|
* @retval kThreadError_NoBufs The maximum number of allowed external multicast addresses are already added.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
ThreadError SubscribeExternalMulticast(const Address &aAddress);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method ussubscribes the network interface to the external (to OpenThread) multicast address.
|
||||||
|
*
|
||||||
|
* @param[in] aAddress A reference to the multicast address.
|
||||||
|
*
|
||||||
|
* @retval kThreadError_None Successfully unsubscribed to the unicast address.
|
||||||
|
* @retval kThreadError_InvalidArgs The address indicated by @p aAddress is an internal address.
|
||||||
|
* @retval kThreadError_NotFound The multicast address was not found.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
ThreadError UnsubscribeExternalMulticast(const Address &aAddress);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method checks if multicast promiscuous mode is enabled on the network interface.
|
||||||
|
*
|
||||||
|
* @retval TRUE If the multicast promiscuous mode is enabled.
|
||||||
|
* @retval FALSE If the multicast promiscuous mode is disabled.
|
||||||
|
*/
|
||||||
|
bool IsMulticastPromiscuousModeEnabled(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method enables multicast promiscuous mode on the network interface.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void EnableMulticastPromiscuousMode(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method disables multicast promiscuous mode on the network interface.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void DisableMulticastPromiscuousMode(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method registers a network interface callback.
|
* This method registers a network interface callback.
|
||||||
*
|
*
|
||||||
@@ -455,6 +512,7 @@ private:
|
|||||||
NetifMulticastAddress *mMulticastAddresses;
|
NetifMulticastAddress *mMulticastAddresses;
|
||||||
int8_t mInterfaceId;
|
int8_t mInterfaceId;
|
||||||
bool mAllRoutersSubscribed;
|
bool mAllRoutersSubscribed;
|
||||||
|
bool mMulticastPromiscuousMode;
|
||||||
Tasklet mStateChangedTask;
|
Tasklet mStateChangedTask;
|
||||||
Netif *mNext;
|
Netif *mNext;
|
||||||
|
|
||||||
@@ -463,6 +521,9 @@ private:
|
|||||||
NetifUnicastAddress mExtUnicastAddresses[OPENTHREAD_CONFIG_MAX_EXT_IP_ADDRS];
|
NetifUnicastAddress mExtUnicastAddresses[OPENTHREAD_CONFIG_MAX_EXT_IP_ADDRS];
|
||||||
uint8_t mMaskExtUnicastAddresses; // Must have enough bits to hold OPENTHREAD_CONFIG_MAX_EXT_IP_ADDRS
|
uint8_t mMaskExtUnicastAddresses; // Must have enough bits to hold OPENTHREAD_CONFIG_MAX_EXT_IP_ADDRS
|
||||||
|
|
||||||
|
NetifMulticastAddress mExtMulticastAddresses[OPENTHREAD_CONFIG_MAX_EXT_MULTICAST_IP_ADDRS];
|
||||||
|
uint8_t mMaskExtMulticastAddresses; // Must have enough bits to hold OPENTHREAD_CONFIG_MAX_EXT_MULTICAST_IP_ADDRS
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method determines if an address is one of the external unicast addresses, and if so returns
|
* This method determines if an address is one of the external unicast addresses, and if so returns
|
||||||
* the index in the mExtUnicastAddresses array.
|
* the index in the mExtUnicastAddresses array.
|
||||||
@@ -480,6 +541,24 @@ private:
|
|||||||
|
|
||||||
return static_cast<int8_t>(address - &mExtUnicastAddresses[0]);
|
return static_cast<int8_t>(address - &mExtUnicastAddresses[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method determines if an address is one of the external multicast addresses, and if so returns
|
||||||
|
* the index in the mExtMulticastAddresses array.
|
||||||
|
*
|
||||||
|
* @param[in] aAddress A pointer to the Network Interface Multicast address.
|
||||||
|
*
|
||||||
|
* @returns The index in the mExtMulticastAddresses array or -1 if not part of the array.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int8_t GetExtMulticastAddressIndex(const NetifMulticastAddress *address) {
|
||||||
|
if (address < &mExtMulticastAddresses[0] ||
|
||||||
|
address >= &mExtMulticastAddresses[0] + OPENTHREAD_CONFIG_MAX_EXT_MULTICAST_IP_ADDRS) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return static_cast<int8_t>(address - &mExtMulticastAddresses[0]);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -125,6 +125,16 @@
|
|||||||
#define OPENTHREAD_CONFIG_MAX_EXT_IP_ADDRS 4
|
#define OPENTHREAD_CONFIG_MAX_EXT_IP_ADDRS 4
|
||||||
#endif // OPENTHREAD_CONFIG_MAX_EXT_IP_ADDRS
|
#endif // OPENTHREAD_CONFIG_MAX_EXT_IP_ADDRS
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @def OPENTHREAD_CONFIG_MAX_EXT_MULTICAST_IP_ADDRS
|
||||||
|
*
|
||||||
|
* The maximum number of supported IPv6 multicast addresses allows to be externally added.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef OPENTHREAD_CONFIG_MAX_EXT_MULTICAST_IP_ADDRS
|
||||||
|
#define OPENTHREAD_CONFIG_MAX_EXT_MULTICAST_IP_ADDRS 2
|
||||||
|
#endif // OPENTHREAD_CONFIG_MAX_EXT_MULTICAST_IP_ADDRS
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @def OPENTHREAD_CONFIG_6LOWPAN_REASSEMBLY_TIMEOUT
|
* @def OPENTHREAD_CONFIG_6LOWPAN_REASSEMBLY_TIMEOUT
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -929,6 +929,36 @@ void otDhcp6ClientUpdate(otInstance *aInstance, otNetifAddress *aAddresses, uint
|
|||||||
}
|
}
|
||||||
#endif // OPENTHREAD_ENABLE_DHCP6_CLIENT
|
#endif // OPENTHREAD_ENABLE_DHCP6_CLIENT
|
||||||
|
|
||||||
|
const otNetifMulticastAddress *otGetMulticastAddresses(otInstance *aInstance)
|
||||||
|
{
|
||||||
|
return aInstance->mThreadNetif.GetMulticastAddresses();
|
||||||
|
}
|
||||||
|
|
||||||
|
ThreadError otSubscribeMulticastAddress(otInstance *aInstance, const otIp6Address *aAddress)
|
||||||
|
{
|
||||||
|
return aInstance->mThreadNetif.SubscribeExternalMulticast(*static_cast<const Ip6::Address *>(aAddress));
|
||||||
|
}
|
||||||
|
|
||||||
|
ThreadError otUnsubscribeMulticastAddress(otInstance *aInstance, const otIp6Address *aAddress)
|
||||||
|
{
|
||||||
|
return aInstance->mThreadNetif.UnsubscribeExternalMulticast(*static_cast<const Ip6::Address *>(aAddress));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool otIsMulticastPromiscuousModeEnabled(otInstance *aInstance)
|
||||||
|
{
|
||||||
|
return aInstance->mThreadNetif.IsMulticastPromiscuousModeEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
void otEnableMulticastPromiscuousMode(otInstance *aInstance)
|
||||||
|
{
|
||||||
|
aInstance->mThreadNetif.EnableMulticastPromiscuousMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
void otDisableMulticastPromiscuousMode(otInstance *aInstance)
|
||||||
|
{
|
||||||
|
aInstance->mThreadNetif.DisableMulticastPromiscuousMode();
|
||||||
|
}
|
||||||
|
|
||||||
void otSlaacUpdate(otInstance *aInstance, otNetifAddress *aAddresses, uint32_t aNumAddresses,
|
void otSlaacUpdate(otInstance *aInstance, otNetifAddress *aAddresses, uint32_t aNumAddresses,
|
||||||
otSlaacIidCreate aIidCreate, void *aContext)
|
otSlaacIidCreate aIidCreate, void *aContext)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user