blob: d6cdfac25b7b28b0fa130813c87f0d902d2eed02 [file] [log] [blame]
/*
* Copyright (c) 2016, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef IP6_MPL_HPP_
#define IP6_MPL_HPP_
/**
* @file
* This file includes definitions for MPL.
*/
#include "openthread-core-config.h"
#include "common/locator.hpp"
#include "common/message.hpp"
#include "common/non_copyable.hpp"
#include "common/timer.hpp"
#include "net/ip6_headers.hpp"
namespace ot {
namespace Ip6 {
/**
* @addtogroup core-ip6-mpl
*
* @brief
* This module includes definitions for MPL.
*
* @{
*
*/
/**
* This class implements MPL header generation and parsing.
*
*/
OT_TOOL_PACKED_BEGIN
class OptionMpl : public OptionHeader
{
public:
static constexpr uint8_t kType = 0x6d; // 01 1 01101
static constexpr uint8_t kMinLength = 2;
/**
* This method initializes the MPL header.
*
*/
void Init(void)
{
OptionHeader::SetType(kType);
OptionHeader::SetLength(sizeof(*this) - sizeof(OptionHeader));
mControl = 0;
}
/**
* This method returns the total MPL Option length value including option
* header.
*
* @returns The total IPv6 Option Length.
*
*/
uint8_t GetTotalLength(void) const { return OptionHeader::GetLength() + sizeof(OptionHeader); }
/**
* MPL Seed Id lengths.
*
*/
enum SeedIdLength : uint8_t
{
kSeedIdLength0 = 0 << 6, ///< 0-byte MPL Seed Id Length.
kSeedIdLength2 = 1 << 6, ///< 2-byte MPL Seed Id Length.
kSeedIdLength8 = 2 << 6, ///< 8-byte MPL Seed Id Length.
kSeedIdLength16 = 3 << 6, ///< 16-byte MPL Seed Id Length.
};
/**
* This method returns the MPL Seed Id Length value.
*
* @returns The MPL Seed Id Length value.
*
*/
SeedIdLength GetSeedIdLength(void) const { return static_cast<SeedIdLength>(mControl & kSeedIdLengthMask); }
/**
* This method sets the MPL Seed Id Length value.
*
* @param[in] aSeedIdLength The MPL Seed Length.
*
*/
void SetSeedIdLength(SeedIdLength aSeedIdLength)
{
mControl = static_cast<uint8_t>((mControl & ~kSeedIdLengthMask) | aSeedIdLength);
}
/**
* This method indicates whether or not the MPL M flag is set.
*
* @retval TRUE If the MPL M flag is set.
* @retval FALSE If the MPL M flag is not set.
*
*/
bool IsMaxFlagSet(void) const { return (mControl & kMaxFlag) != 0; }
/**
* This method clears the MPL M flag.
*
*/
void ClearMaxFlag(void) { mControl &= ~kMaxFlag; }
/**
* This method sets the MPL M flag.
*
*/
void SetMaxFlag(void) { mControl |= kMaxFlag; }
/**
* This method returns the MPL Sequence value.
*
* @returns The MPL Sequence value.
*
*/
uint8_t GetSequence(void) const { return mSequence; }
/**
* This method sets the MPL Sequence value.
*
* @param[in] aSequence The MPL Sequence value.
*
*/
void SetSequence(uint8_t aSequence) { mSequence = aSequence; }
/**
* This method returns the MPL Seed Id value.
*
* @returns The MPL Seed Id value.
*
*/
uint16_t GetSeedId(void) const { return HostSwap16(mSeedId); }
/**
* This method sets the MPL Seed Id value.
*
* @param[in] aSeedId The MPL Seed Id value.
*
*/
void SetSeedId(uint16_t aSeedId) { mSeedId = HostSwap16(aSeedId); }
private:
static constexpr uint8_t kSeedIdLengthMask = 3 << 6;
static constexpr uint8_t kMaxFlag = 1 << 5;
uint8_t mControl;
uint8_t mSequence;
uint16_t mSeedId;
} OT_TOOL_PACKED_END;
/**
* This class implements MPL message processing.
*
*/
class Mpl : public InstanceLocator, private NonCopyable
{
public:
/**
* This constructor initializes the MPL object.
*
* @param[in] aInstance A reference to the OpenThread instance.
*
*/
explicit Mpl(Instance &aInstance);
/**
* This method initializes the MPL option.
*
* @param[in] aOption A reference to the MPL header to initialize.
* @param[in] aAddress A reference to the IPv6 Source Address.
*
*/
void InitOption(OptionMpl &aOption, const Address &aAddress);
/**
* This method processes an MPL option. When the MPL module acts as an MPL Forwarder
* it disseminates MPL Data Message using Trickle timer expirations. When acts as an
* MPL Seed it allows to send the first MPL Data Message directly, then sets up Trickle
* timer expirations for subsequent retransmissions.
*
* @param[in] aMessage A reference to the message.
* @param[in] aAddress A reference to the IPv6 Source Address.
* @param[in] aIsOutbound TRUE if this message was locally generated, FALSE otherwise.
* @param[out] aReceive Set to FALSE if the MPL message is a duplicate and must not
* go through the receiving process again, untouched otherwise.
*
* @retval kErrorNone Successfully processed the MPL option.
* @retval kErrorDrop The MPL message is a duplicate and should be dropped.
*
*/
Error ProcessOption(Message &aMessage, const Address &aAddress, bool aIsOutbound, bool &aReceive);
/**
* This method returns the MPL Seed Id value.
*
* @returns The MPL Seed Id value.
*
*/
uint16_t GetSeedId(void) const { return mSeedId; }
/**
* This method sets the MPL Seed Id value.
*
* @param[in] aSeedId The MPL Seed Id value.
*
*/
void SetSeedId(uint16_t aSeedId) { mSeedId = aSeedId; }
/**
* This method sets the IPv6 matching address, that allows to elide MPL Seed Id.
*
* @param[in] aAddress The reference to the IPv6 matching address.
*
*/
void SetMatchingAddress(const Address &aAddress) { mMatchingAddress = &aAddress; }
#if OPENTHREAD_FTD
/**
* This method gets the MPL number of Trickle timer expirations that occur before
* terminating the Trickle algorithm's retransmission of a given MPL Data Message.
*
* @returns The MPL number of Trickle timer expirations.
*
*/
uint8_t GetTimerExpirations(void) const { return mTimerExpirations; }
/**
* This method sets the MPL number of Trickle timer expirations that occur before
* terminating the Trickle algorithm's retransmission of a given MPL Data Message.
*
* @param[in] aTimerExpirations The number of Trickle timer expirations.
*
*/
void SetTimerExpirations(uint8_t aTimerExpirations) { mTimerExpirations = aTimerExpirations; }
/**
* This method returns a reference to the buffered message set.
*
* @returns A reference to the buffered message set.
*
*/
const MessageQueue &GetBufferedMessageSet(void) const { return mBufferedMessageSet; }
#endif // OPENTHREAD_FTD
private:
static constexpr uint16_t kNumSeedEntries = OPENTHREAD_CONFIG_MPL_SEED_SET_ENTRIES;
static constexpr uint32_t kSeedEntryLifetime = OPENTHREAD_CONFIG_MPL_SEED_SET_ENTRY_LIFETIME;
static constexpr uint32_t kSeedEntryLifetimeDt = 1000;
static constexpr uint8_t kDataMessageInterval = 64;
struct SeedEntry
{
uint16_t mSeedId;
uint8_t mSequence;
uint8_t mLifetime;
};
static void HandleSeedSetTimer(Timer &aTimer);
void HandleSeedSetTimer(void);
Error UpdateSeedSet(uint16_t aSeedId, uint8_t aSequence);
SeedEntry mSeedSet[kNumSeedEntries];
const Address *mMatchingAddress;
TimerMilli mSeedSetTimer;
uint16_t mSeedId;
uint8_t mSequence;
#if OPENTHREAD_FTD
struct Metadata
{
Error AppendTo(Message &aMessage) const { return aMessage.Append(*this); }
void ReadFrom(const Message &aMessage);
void RemoveFrom(Message &aMessage) const;
void UpdateIn(Message &aMessage) const;
void GenerateNextTransmissionTime(TimeMilli aCurrentTime, uint8_t aInterval);
TimeMilli mTransmissionTime;
uint16_t mSeedId;
uint8_t mSequence;
uint8_t mTransmissionCount;
uint8_t mIntervalOffset;
};
static void HandleRetransmissionTimer(Timer &aTimer);
void HandleRetransmissionTimer(void);
void AddBufferedMessage(Message &aMessage, uint16_t aSeedId, uint8_t aSequence, bool aIsOutbound);
MessageQueue mBufferedMessageSet;
TimerMilli mRetransmissionTimer;
uint8_t mTimerExpirations;
#endif // OPENTHREAD_FTD
};
/**
* @}
*
*/
} // namespace Ip6
} // namespace ot
#endif // IP6_MPL_HPP_