Skip to content

Commit

Permalink
IPv6 multicast build method added to PeerAddress (#11368)
Browse files Browse the repository at this point in the history
* PeerAddress: Added methods to construct the IPv6 Multicast Address.

* PeerAddress: Code review comments applied.
  • Loading branch information
rcasallas-silabs authored and pull[bot] committed Jan 26, 2022
1 parent 95a5422 commit 1434288
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 1 deletion.
18 changes: 18 additions & 0 deletions src/transport/raw/PeerAddress.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ class PeerAddress

bool IsInitialized() const { return mTransportType != Type::kUndefined; }

bool IsMulticast() { return Type::kUdp == mTransportType && mIPAddress.IsIPv6Multicast(); }

bool operator==(const PeerAddress & other) const
{
return (mTransportType == other.mTransportType) && (mIPAddress == other.mIPAddress) && (mPort == other.mPort) &&
Expand Down Expand Up @@ -201,6 +203,22 @@ class PeerAddress
return TCP(addr).SetPort(port).SetInterface(interface);
}

static PeerAddress Multicast(chip::FabricId fabric, chip::GroupId group)
{
constexpr uint8_t scope = 0x05; // Site-Local
constexpr uint8_t prefixLength = 0x40; // 64-bit long network prefix field
// The network prefix portion of the Multicast Address is the 64-bit bitstring formed by concatenating:
// * 0xFD to designate a locally assigned ULA prefix
// * The upper 56-bits of the Fabric ID for the network in big-endian order
const uint64_t prefix = 0xfd00000000000000 | ((fabric >> 8) & 0x00ffffffffffffff);
// The 32-bit group identifier portion of the Multicast Address is the 32-bits formed by:
// * The lower 8-bits of the Fabric ID
// * 0x00
// * The 16-bits Group Identifier in big-endian order
uint32_t groupId = static_cast<uint32_t>((fabric << 24) & 0xff000000) | group;
return UDP(Inet::IPAddress::MakeIPv6PrefixMulticast(scope, prefixLength, prefix, groupId));
}

private:
Inet::IPAddress mIPAddress = {};
Type mTransportType = Type::kUndefined;
Expand Down
5 changes: 4 additions & 1 deletion src/transport/raw/tests/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,10 @@ static_library("helpers") {
chip_test_suite("tests") {
output_name = "libRawTransportTests"

test_sources = [ "TestMessageHeader.cpp" ]
test_sources = [
"TestMessageHeader.cpp",
"TestPeerAddress.cpp",
]

if (current_os != "mac") {
test_sources += [ "TestTCP.cpp" ]
Expand Down
95 changes: 95 additions & 0 deletions src/transport/raw/tests/TestPeerAddress.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
*
* Copyright (c) 2020 Project CHIP Authors
* Copyright (c) 2016-2017 Nest Labs, Inc.
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS
#endif

#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS
#endif

#include <inttypes.h>
#include <stdint.h>
#include <string.h>

#include <inet/IPAddress.h>
#include <lib/core/DataModelTypes.h>
#include <lib/core/PeerId.h>
#include <lib/support/UnitTestRegistration.h>
#include <transport/raw/PeerAddress.h>

#include <nlunit-test.h>

using namespace chip;

/**
* Test correct identification of IPv6 multicast addresses.
*/
void TestPeerAddressMulticast(nlTestSuite * inSuite, void * inContext)
{
constexpr chip::FabricId fabric = 0xa1a2a4a8b1b2b4b8;
constexpr chip::GroupId group = 0xe10f;
chip::Transport::PeerAddress addr = chip::Transport::PeerAddress::Multicast(fabric, group);
NL_TEST_ASSERT(inSuite, chip::Transport::Type::kUdp == addr.GetTransportType());
NL_TEST_ASSERT(inSuite, addr.IsMulticast());

const Inet::IPAddress & ip = addr.GetIPAddress();
NL_TEST_ASSERT(inSuite, ip.IsIPv6Multicast());
NL_TEST_ASSERT(inSuite, chip::Inet::IPAddressType::kIPv6 == ip.Type());

constexpr uint8_t expected[NL_INET_IPV6_ADDR_LEN_IN_BYTES] = { 0xff, 0x35, 0x00, 0x40, 0xfd, 0xa1, 0xa2, 0xa4,
0xa8, 0xb1, 0xb2, 0xb4, 0xb8, 0x00, 0xe1, 0x0f };
uint8_t result[NL_INET_IPV6_ADDR_LEN_IN_BYTES];
uint8_t * p = result;
ip.WriteAddress(p);
NL_TEST_ASSERT(inSuite, !memcmp(expected, result, NL_INET_IPV6_ADDR_LEN_IN_BYTES));
}

/**
* Test Suite. It lists all the test functions.
*/

// clang-format off
static const nlTest sTests[] =
{
NL_TEST_DEF("PeerAddress Multicast", TestPeerAddressMulticast),
NL_TEST_SENTINEL()
};
// clang-format on

int TestPeerAddress(void)
{
// clang-format off
nlTestSuite theSuite =
{
"PeerAddress",
&sTests[0],
nullptr,
nullptr
};
// clang-format on

// Run test suit againt one context.
nlTestRunner(&theSuite, nullptr);

return (nlTestRunnerStats(&theSuite));
}

CHIP_REGISTER_TEST_SUITE(TestPeerAddress)

0 comments on commit 1434288

Please sign in to comment.