[ncp] Support for multicast address table (#2001)

This commit adds a new spinel property (along with its prop handlers)
`SPINEL_PROP_IPV6_MULTICAST_ADDRESS_TABLE` to provide the list of
multicast IPv6 addresses.

It also adds `OT_CHANGED_IP6_MULTICAST_SUBSRCRIBED` and
`OT_CHANGED_IP6_MULTICAST_UNSUBSRCRIBED` to flags used in
`NetifCallback` to indicate changes in multicast address list.
This commit is contained in:
Abtin Keshavarzian
2017-07-17 20:58:56 -07:00
committed by Jonathan Hui
parent fdc3ea2732
commit 5ba896266c
7 changed files with 156 additions and 0 deletions
@@ -22,6 +22,7 @@ IPv6 Prefix + Prefix Length
* Type: Read-Write
* Packed-Encoding: `A(t(6CLLC))`
This property provides all unicast addresses.
Array of structures containing:
* `6`: IPv6 Address
@@ -39,3 +40,10 @@ turned on, ping request ICMP packets will not be passed to the host.
Default value is `false`.
### PROP 102: SPINEL_PROP_IPV6_MULTICAST_ADDRESS_TABLE {#prop-ipv6-multicast-address-table}
* Type: Read-Write
* Packed-Encoding: `A(t(6))`
Array of structures containing:
* `6`: Multicast IPv6 Address
+2
View File
@@ -653,6 +653,8 @@ enum
OT_CHANGED_THREAD_NETDATA = 1 << 9, ///< Thread Network Data changed
OT_CHANGED_THREAD_CHILD_ADDED = 1 << 10, ///< Child was added
OT_CHANGED_THREAD_CHILD_REMOVED = 1 << 11, ///< Child was removed
OT_CHANGED_IP6_MULTICAST_SUBSRCRIBED = 1 << 12, ///< Subscribed to a IPv6 multicast address
OT_CHANGED_IP6_MULTICAST_UNSUBSRCRIBED = 1 << 13, ///< Unsubscribed from a IPv6 multicast address
};
/**
+10
View File
@@ -156,6 +156,7 @@ otError Netif::SubscribeMulticast(NetifMulticastAddress &aAddress)
aAddress.mNext = mMulticastAddresses;
mMulticastAddresses = &aAddress;
SetStateChangedFlags(OT_CHANGED_IP6_MULTICAST_SUBSRCRIBED);
exit:
return error;
@@ -185,6 +186,12 @@ otError Netif::UnsubscribeMulticast(const NetifMulticastAddress &aAddress)
ExitNow(error = OT_ERROR_NOT_FOUND);
exit:
if (error != OT_ERROR_NOT_FOUND)
{
SetStateChangedFlags(OT_CHANGED_IP6_MULTICAST_UNSUBSRCRIBED);
}
return error;
}
@@ -215,6 +222,7 @@ otError Netif::SubscribeExternalMulticast(const Address &aAddress)
entry->mAddress = aAddress;
entry->mNext = mMulticastAddresses;
mMulticastAddresses = entry;
SetStateChangedFlags(OT_CHANGED_IP6_MULTICAST_SUBSRCRIBED);
exit:
return error;
@@ -254,6 +262,8 @@ otError Netif::UnsubscribeExternalMulticast(const Address &aAddress)
// To mark the address entry as unused/available, set the `mNext` pointer back to the entry itself.
entry->mNext = entry;
SetStateChangedFlags(OT_CHANGED_IP6_MULTICAST_UNSUBSRCRIBED);
exit:
return error;
}
+126
View File
@@ -184,6 +184,7 @@ const NcpBase::GetPropertyHandlerEntry NcpBase::mGetPropertyHandlerTable[] =
NCP_GET_PROP_HANDLER_ENTRY(IPV6_ADDRESS_TABLE),
NCP_GET_PROP_HANDLER_ENTRY(IPV6_ROUTE_TABLE),
NCP_GET_PROP_HANDLER_ENTRY(IPV6_ICMP_PING_OFFLOAD),
NCP_GET_PROP_HANDLER_ENTRY(IPV6_MULTICAST_ADDRESS_TABLE),
NCP_GET_PROP_HANDLER_ENTRY(THREAD_RLOC16_DEBUG_PASSTHRU),
NCP_GET_PROP_HANDLER_ENTRY(THREAD_DISCOVERY_SCAN_JOINER_FLAG),
NCP_GET_PROP_HANDLER_ENTRY(THREAD_DISCOVERY_SCAN_ENABLE_FILTERING),
@@ -372,6 +373,7 @@ const NcpBase::InsertPropertyHandlerEntry NcpBase::mInsertPropertyHandlerTable[]
NCP_INSERT_PROP_HANDLER_ENTRY(MAC_SRC_MATCH_EXTENDED_ADDRESSES),
#endif
NCP_INSERT_PROP_HANDLER_ENTRY(IPV6_ADDRESS_TABLE),
NCP_INSERT_PROP_HANDLER_ENTRY(IPV6_MULTICAST_ADDRESS_TABLE),
NCP_INSERT_PROP_HANDLER_ENTRY(THREAD_ASSISTING_PORTS),
#if OPENTHREAD_ENABLE_BORDER_ROUTER
NCP_INSERT_PROP_HANDLER_ENTRY(THREAD_OFF_MESH_ROUTES),
@@ -396,6 +398,7 @@ const NcpBase::RemovePropertyHandlerEntry NcpBase::mRemovePropertyHandlerTable[]
NCP_REMOVE_PROP_HANDLER_ENTRY(MAC_SRC_MATCH_EXTENDED_ADDRESSES),
#endif
NCP_REMOVE_PROP_HANDLER_ENTRY(IPV6_ADDRESS_TABLE),
NCP_REMOVE_PROP_HANDLER_ENTRY(IPV6_MULTICAST_ADDRESS_TABLE),
#if OPENTHREAD_ENABLE_BORDER_ROUTER
NCP_REMOVE_PROP_HANDLER_ENTRY(THREAD_OFF_MESH_ROUTES),
NCP_REMOVE_PROP_HANDLER_ENTRY(THREAD_ON_MESH_NETS),
@@ -1340,6 +1343,17 @@ void NcpBase::UpdateChangedProps(void)
mChangedFlags &= ~static_cast<uint32_t>(OT_CHANGED_IP6_ADDRESS_ADDED | OT_CHANGED_IP6_ADDRESS_REMOVED);
}
else if ((mChangedFlags & (OT_CHANGED_IP6_MULTICAST_SUBSRCRIBED | OT_CHANGED_IP6_MULTICAST_UNSUBSRCRIBED)) != 0)
{
SuccessOrExit(
HandleCommandPropertyGet(
SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0,
SPINEL_PROP_IPV6_MULTICAST_ADDRESS_TABLE
));
mChangedFlags &= ~static_cast<uint32_t>(OT_CHANGED_IP6_MULTICAST_SUBSRCRIBED |
OT_CHANGED_IP6_MULTICAST_UNSUBSRCRIBED);
}
else if ((mChangedFlags & (OT_CHANGED_THREAD_CHILD_ADDED | OT_CHANGED_THREAD_CHILD_REMOVED)) != 0)
{
SuccessOrExit(
@@ -3430,6 +3444,40 @@ otError NcpBase::GetPropertyHandler_IPV6_ICMP_PING_OFFLOAD(uint8_t aHeader, spin
);
}
otError NcpBase::GetPropertyHandler_IPV6_MULTICAST_ADDRESS_TABLE(uint8_t aHeader, spinel_prop_key_t aKey)
{
otError error = OT_ERROR_NONE;
const otNetifMulticastAddress *address;
mDisableStreamWrite = true;
SuccessOrExit(error = OutboundFrameBegin(aHeader));
SuccessOrExit(
error = OutboundFrameFeedPacked(
SPINEL_DATATYPE_COMMAND_PROP_S,
aHeader,
SPINEL_CMD_PROP_VALUE_IS,
aKey
));
for (address = otIp6GetMulticastAddresses(mInstance); address; address = address->mNext)
{
SuccessOrExit(
error = OutboundFrameFeedPacked(
SPINEL_DATATYPE_STRUCT_S(
SPINEL_DATATYPE_IPv6ADDR_S // IPv6 address
),
&address->mAddress
));
}
SuccessOrExit(error = OutboundFrameSend());
exit:
mDisableStreamWrite = false;
return error;
}
otError NcpBase::GetPropertyHandler_THREAD_RLOC16_DEBUG_PASSTHRU(uint8_t aHeader, spinel_prop_key_t aKey)
{
// Note reverse logic: passthru enabled = filter disabled
@@ -6804,6 +6852,46 @@ exit:
return error;
}
otError NcpBase::InsertPropertyHandler_IPV6_MULTICAST_ADDRESS_TABLE(uint8_t aHeader, spinel_prop_key_t aKey,
const uint8_t *aValuePtr, uint16_t aValueLen)
{
spinel_ssize_t parsedLength;
otError error = OT_ERROR_NONE;
spinel_status_t spinelError = SPINEL_STATUS_OK;
otIp6Address *addrPtr;
parsedLength = spinel_datatype_unpack(
aValuePtr,
aValueLen,
SPINEL_DATATYPE_IPv6ADDR_S, // IPv6 address
&addrPtr
);
VerifyOrExit(parsedLength > 0, spinelError = SPINEL_STATUS_PARSE_ERROR);
error = otIp6SubscribeMulticastAddress(mInstance, addrPtr);
VerifyOrExit(error == OT_ERROR_NONE, spinelError = ThreadErrorToSpinelStatus(error));
error = SendPropertyUpdate(
aHeader,
SPINEL_CMD_PROP_VALUE_INSERTED,
aKey,
aValuePtr,
aValueLen
);
spinelError = SPINEL_STATUS_OK;
exit:
if (spinelError != SPINEL_STATUS_OK)
{
error = SendLastStatus(aHeader, spinelError);
}
return error;
}
#if OPENTHREAD_ENABLE_BORDER_ROUTER
otError NcpBase::InsertPropertyHandler_THREAD_OFF_MESH_ROUTES(uint8_t aHeader, spinel_prop_key_t aKey,
const uint8_t *aValuePtr, uint16_t aValueLen)
@@ -7305,6 +7393,44 @@ exit:
return error;
}
otError NcpBase::RemovePropertyHandler_IPV6_MULTICAST_ADDRESS_TABLE(uint8_t aHeader, spinel_prop_key_t aKey,
const uint8_t *aValuePtr, uint16_t aValueLen)
{
spinel_ssize_t parsedLength;
otError error = OT_ERROR_NONE;
spinel_status_t spinelError = SPINEL_STATUS_OK;
otIp6Address *addrPtr;
parsedLength = spinel_datatype_unpack(
aValuePtr,
aValueLen,
SPINEL_DATATYPE_IPv6ADDR_S,
&addrPtr
);
VerifyOrExit(parsedLength > 0, spinelError = SPINEL_STATUS_PARSE_ERROR);
error = otIp6UnsubscribeMulticastAddress(mInstance, addrPtr);
VerifyOrExit(error == OT_ERROR_NONE, spinelError = ThreadErrorToSpinelStatus(error));
error = SendPropertyUpdate(
aHeader,
SPINEL_CMD_PROP_VALUE_REMOVED,
aKey,
aValuePtr,
aValueLen
);
exit:
if (spinelError != SPINEL_STATUS_OK)
{
error = SendLastStatus(aHeader, spinelError);
}
return error;
}
#if OPENTHREAD_ENABLE_BORDER_ROUTER
otError NcpBase::RemovePropertyHandler_THREAD_OFF_MESH_ROUTES(uint8_t aHeader, spinel_prop_key_t aKey,
const uint8_t *aValuePtr, uint16_t aValueLen)
+3
View File
@@ -375,6 +375,7 @@ private:
NCP_GET_PROP_HANDLER(IPV6_ADDRESS_TABLE);
NCP_GET_PROP_HANDLER(IPV6_ROUTE_TABLE);
NCP_GET_PROP_HANDLER(IPV6_ICMP_PING_OFFLOAD);
NCP_GET_PROP_HANDLER(IPV6_MULTICAST_ADDRESS_TABLE);
NCP_GET_PROP_HANDLER(THREAD_RLOC16_DEBUG_PASSTHRU);
NCP_GET_PROP_HANDLER(THREAD_OFF_MESH_ROUTES);
NCP_GET_PROP_HANDLER(STREAM_NET);
@@ -543,6 +544,7 @@ private:
NCP_INSERT_PROP_HANDLER(MAC_SRC_MATCH_EXTENDED_ADDRESSES);
#endif
NCP_INSERT_PROP_HANDLER(IPV6_ADDRESS_TABLE);
NCP_INSERT_PROP_HANDLER(IPV6_MULTICAST_ADDRESS_TABLE);
#if OPENTHREAD_ENABLE_BORDER_ROUTER
NCP_INSERT_PROP_HANDLER(THREAD_OFF_MESH_ROUTES);
NCP_INSERT_PROP_HANDLER(THREAD_ON_MESH_NETS);
@@ -564,6 +566,7 @@ private:
NCP_REMOVE_PROP_HANDLER(MAC_SRC_MATCH_EXTENDED_ADDRESSES);
#endif
NCP_REMOVE_PROP_HANDLER(IPV6_ADDRESS_TABLE);
NCP_REMOVE_PROP_HANDLER(IPV6_MULTICAST_ADDRESS_TABLE);
#if OPENTHREAD_ENABLE_BORDER_ROUTER
NCP_REMOVE_PROP_HANDLER(THREAD_OFF_MESH_ROUTES);
NCP_REMOVE_PROP_HANDLER(THREAD_ON_MESH_NETS);
+4
View File
@@ -1332,6 +1332,10 @@ spinel_prop_key_to_cstr(spinel_prop_key_t prop_key)
ret = "PROP_IPV6_ICMP_PING_OFFLOAD";
break;
case SPINEL_PROP_IPV6_MULTICAST_ADDRESS_TABLE:
ret = "PROP_IPV6_MULTICAST_ADDRESS_TABLE";
break;
case SPINEL_PROP_STREAM_DEBUG:
ret = "PROP_STREAM_DEBUG";
break;
+3
View File
@@ -990,6 +990,9 @@ typedef enum
*/
SPINEL_PROP_IPV6_ICMP_PING_OFFLOAD = SPINEL_PROP_IPV6__BEGIN + 5, ///< [b]
SPINEL_PROP_IPV6_MULTICAST_ADDRESS_TABLE
= SPINEL_PROP_IPV6__BEGIN + 6, ///< [A(t(6))]
SPINEL_PROP_IPV6__END = 0x70,
SPINEL_PROP_STREAM__BEGIN = 0x70,