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