1 /* 2 * Copyright (c) 2016, The OpenThread Authors. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 3. Neither the name of the copyright holder nor the 13 * names of its contributors may be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #ifndef IP6_MPL_HPP_ 30 #define IP6_MPL_HPP_ 31 32 /** 33 * @file 34 * This file includes definitions for MPL. 35 */ 36 37 #include "openthread-core-config.h" 38 39 #include "common/locator.hpp" 40 #include "common/message.hpp" 41 #include "common/non_copyable.hpp" 42 #include "common/time_ticker.hpp" 43 #include "common/timer.hpp" 44 #include "net/ip6_headers.hpp" 45 46 namespace ot { 47 namespace Ip6 { 48 49 /** 50 * @addtogroup core-ip6-mpl 51 * 52 * @brief 53 * This module includes definitions for MPL. 54 * 55 * @{ 56 * 57 */ 58 59 /** 60 * Implements MPL header generation and parsing. 61 * 62 */ 63 OT_TOOL_PACKED_BEGIN 64 class MplOption : public Option 65 { 66 public: 67 static constexpr uint8_t kType = 0x6d; ///< MPL option type - 01 1 01101 68 static constexpr uint8_t kMinSize = (2 + sizeof(Option)); ///< Minimum size (num of bytes) of `MplOption` 69 70 /** 71 * MPL Seed Id Lengths. 72 * 73 */ 74 enum SeedIdLength : uint8_t 75 { 76 kSeedIdLength0 = 0 << 6, ///< 0-byte MPL Seed Id Length. 77 kSeedIdLength2 = 1 << 6, ///< 2-byte MPL Seed Id Length. 78 kSeedIdLength8 = 2 << 6, ///< 8-byte MPL Seed Id Length. 79 kSeedIdLength16 = 3 << 6, ///< 16-byte MPL Seed Id Length. 80 }; 81 82 /** 83 * Initializes the MPL Option. 84 * 85 * The @p aSeedIdLength MUST be either `kSeedIdLength0` or `kSeedIdLength2`. Other values are not supported. 86 * 87 * @param[in] aSeedIdLength The MPL Seed Id Length. 88 * 89 */ 90 void Init(SeedIdLength aSeedIdLength); 91 92 /** 93 * Returns the MPL Seed Id Length value. 94 * 95 * @returns The MPL Seed Id Length value. 96 * 97 */ GetSeedIdLength(void) const98 SeedIdLength GetSeedIdLength(void) const { return static_cast<SeedIdLength>(mControl & kSeedIdLengthMask); } 99 100 /** 101 * Indicates whether or not the MPL M flag is set. 102 * 103 * @retval TRUE If the MPL M flag is set. 104 * @retval FALSE If the MPL M flag is not set. 105 * 106 */ IsMaxFlagSet(void) const107 bool IsMaxFlagSet(void) const { return (mControl & kMaxFlag) != 0; } 108 109 /** 110 * Clears the MPL M flag. 111 * 112 */ ClearMaxFlag(void)113 void ClearMaxFlag(void) { mControl &= ~kMaxFlag; } 114 115 /** 116 * Sets the MPL M flag. 117 * 118 */ SetMaxFlag(void)119 void SetMaxFlag(void) { mControl |= kMaxFlag; } 120 121 /** 122 * Returns the MPL Sequence value. 123 * 124 * @returns The MPL Sequence value. 125 * 126 */ GetSequence(void) const127 uint8_t GetSequence(void) const { return mSequence; } 128 129 /** 130 * Sets the MPL Sequence value. 131 * 132 * @param[in] aSequence The MPL Sequence value. 133 * 134 */ SetSequence(uint8_t aSequence)135 void SetSequence(uint8_t aSequence) { mSequence = aSequence; } 136 137 /** 138 * Returns the MPL Seed Id value. 139 * 140 * @returns The MPL Seed Id value. 141 * 142 */ GetSeedId(void) const143 uint16_t GetSeedId(void) const { return BigEndian::HostSwap16(mSeedId); } 144 145 /** 146 * Sets the MPL Seed Id value. 147 * 148 * @param[in] aSeedId The MPL Seed Id value. 149 * 150 */ SetSeedId(uint16_t aSeedId)151 void SetSeedId(uint16_t aSeedId) { mSeedId = BigEndian::HostSwap16(aSeedId); } 152 153 private: 154 static constexpr uint8_t kSeedIdLengthMask = 3 << 6; 155 static constexpr uint8_t kMaxFlag = 1 << 5; 156 157 uint8_t mControl; 158 uint8_t mSequence; 159 uint16_t mSeedId; 160 } OT_TOOL_PACKED_END; 161 162 /** 163 * Implements MPL message processing. 164 * 165 */ 166 class Mpl : public InstanceLocator, private NonCopyable 167 { 168 friend class ot::TimeTicker; 169 170 public: 171 /** 172 * Initializes the MPL object. 173 * 174 * @param[in] aInstance A reference to the OpenThread instance. 175 * 176 */ 177 explicit Mpl(Instance &aInstance); 178 179 /** 180 * Initializes the MPL option. 181 * 182 * @param[in] aOption A reference to the MPL header to initialize. 183 * @param[in] aAddress A reference to the IPv6 Source Address. 184 * 185 */ 186 void InitOption(MplOption &aOption, const Address &aAddress); 187 188 /** 189 * Processes an MPL option. When the MPL module acts as an MPL Forwarder 190 * it disseminates MPL Data Message using Trickle timer expirations. When acts as an 191 * MPL Seed it allows to send the first MPL Data Message directly, then sets up Trickle 192 * timer expirations for subsequent retransmissions. 193 * 194 * @param[in] aMessage A reference to the message. 195 * @param[in] aOffset The offset in @p aMessage to read the MPL option. 196 * @param[in] aAddress A reference to the IPv6 Source Address. 197 * @param[out] aReceive Set to FALSE if the MPL message is a duplicate and must not 198 * go through the receiving process again, untouched otherwise. 199 * 200 * @retval kErrorNone Successfully processed the MPL option. 201 * @retval kErrorDrop The MPL message is a duplicate and should be dropped. 202 * 203 */ 204 Error ProcessOption(Message &aMessage, uint16_t aOffset, const Address &aAddress, bool &aReceive); 205 206 #if OPENTHREAD_FTD 207 /** 208 * Returns a reference to the buffered message set. 209 * 210 * @returns A reference to the buffered message set. 211 * 212 */ GetBufferedMessageSet(void) const213 const MessageQueue &GetBufferedMessageSet(void) const { return mBufferedMessageSet; } 214 #endif 215 216 private: 217 static constexpr uint16_t kNumSeedEntries = OPENTHREAD_CONFIG_MPL_SEED_SET_ENTRIES; 218 static constexpr uint32_t kSeedEntryLifetime = OPENTHREAD_CONFIG_MPL_SEED_SET_ENTRY_LIFETIME; 219 static constexpr uint32_t kSeedEntryLifetimeDt = 1000; 220 static constexpr uint8_t kDataMessageInterval = 64; 221 222 struct SeedEntry 223 { 224 uint16_t mSeedId; 225 uint8_t mSequence; 226 uint8_t mLifetime; 227 }; 228 229 void HandleTimeTick(void); 230 Error UpdateSeedSet(uint16_t aSeedId, uint8_t aSequence); 231 232 SeedEntry mSeedSet[kNumSeedEntries]; 233 uint8_t mSequence; 234 235 #if OPENTHREAD_FTD 236 static constexpr uint8_t kChildRetransmissions = 0; // MPL retransmissions for Children. 237 static constexpr uint8_t kRouterRetransmissions = 2; // MPL retransmissions for Routers. 238 239 struct Metadata 240 { AppendToot::Ip6::Mpl::Metadata241 Error AppendTo(Message &aMessage) const { return aMessage.Append(*this); } 242 void ReadFrom(const Message &aMessage); 243 void RemoveFrom(Message &aMessage) const; 244 void UpdateIn(Message &aMessage) const; 245 void GenerateNextTransmissionTime(TimeMilli aCurrentTime, uint8_t aInterval); 246 247 TimeMilli mTransmissionTime; 248 uint16_t mSeedId; 249 uint8_t mSequence; 250 uint8_t mTransmissionCount; 251 uint8_t mIntervalOffset; 252 }; 253 254 uint8_t DetermineMaxRetransmissions(void) const; 255 void HandleRetransmissionTimer(void); 256 void AddBufferedMessage(Message &aMessage, uint16_t aSeedId, uint8_t aSequence); 257 258 using RetxTimer = TimerMilliIn<Mpl, &Mpl::HandleRetransmissionTimer>; 259 260 MessageQueue mBufferedMessageSet; 261 RetxTimer mRetransmissionTimer; 262 #endif // OPENTHREAD_FTD 263 }; 264 265 /** 266 * @} 267 * 268 */ 269 270 } // namespace Ip6 271 } // namespace ot 272 273 #endif // IP6_MPL_HPP_ 274