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/timer.hpp"
43 #include "net/ip6_headers.hpp"
44 
45 namespace ot {
46 namespace Ip6 {
47 
48 /**
49  * @addtogroup core-ip6-mpl
50  *
51  * @brief
52  *   This module includes definitions for MPL.
53  *
54  * @{
55  *
56  */
57 
58 /**
59  * This class implements MPL header generation and parsing.
60  *
61  */
62 OT_TOOL_PACKED_BEGIN
63 class OptionMpl : public OptionHeader
64 {
65 public:
66     static constexpr uint8_t kType      = 0x6d; // 01 1 01101
67     static constexpr uint8_t kMinLength = 2;
68 
69     /**
70      * This method initializes the MPL header.
71      *
72      */
Init(void)73     void Init(void)
74     {
75         OptionHeader::SetType(kType);
76         OptionHeader::SetLength(sizeof(*this) - sizeof(OptionHeader));
77         mControl = 0;
78     }
79 
80     /**
81      * This method returns the total MPL Option length value including option
82      * header.
83      *
84      * @returns The total IPv6 Option Length.
85      *
86      */
GetTotalLength(void) const87     uint8_t GetTotalLength(void) const { return OptionHeader::GetLength() + sizeof(OptionHeader); }
88 
89     /**
90      * MPL Seed Id lengths.
91      *
92      */
93     enum SeedIdLength : uint8_t
94     {
95         kSeedIdLength0  = 0 << 6, ///< 0-byte MPL Seed Id Length.
96         kSeedIdLength2  = 1 << 6, ///< 2-byte MPL Seed Id Length.
97         kSeedIdLength8  = 2 << 6, ///< 8-byte MPL Seed Id Length.
98         kSeedIdLength16 = 3 << 6, ///< 16-byte MPL Seed Id Length.
99     };
100 
101     /**
102      * This method returns the MPL Seed Id Length value.
103      *
104      * @returns The MPL Seed Id Length value.
105      *
106      */
GetSeedIdLength(void) const107     SeedIdLength GetSeedIdLength(void) const { return static_cast<SeedIdLength>(mControl & kSeedIdLengthMask); }
108 
109     /**
110      * This method sets the MPL Seed Id Length value.
111      *
112      * @param[in]  aSeedIdLength  The MPL Seed Length.
113      *
114      */
SetSeedIdLength(SeedIdLength aSeedIdLength)115     void SetSeedIdLength(SeedIdLength aSeedIdLength)
116     {
117         mControl = static_cast<uint8_t>((mControl & ~kSeedIdLengthMask) | aSeedIdLength);
118     }
119 
120     /**
121      * This method indicates whether or not the MPL M flag is set.
122      *
123      * @retval TRUE   If the MPL M flag is set.
124      * @retval FALSE  If the MPL M flag is not set.
125      *
126      */
IsMaxFlagSet(void) const127     bool IsMaxFlagSet(void) const { return (mControl & kMaxFlag) != 0; }
128 
129     /**
130      * This method clears the MPL M flag.
131      *
132      */
ClearMaxFlag(void)133     void ClearMaxFlag(void) { mControl &= ~kMaxFlag; }
134 
135     /**
136      * This method sets the MPL M flag.
137      *
138      */
SetMaxFlag(void)139     void SetMaxFlag(void) { mControl |= kMaxFlag; }
140 
141     /**
142      * This method returns the MPL Sequence value.
143      *
144      * @returns The MPL Sequence value.
145      *
146      */
GetSequence(void) const147     uint8_t GetSequence(void) const { return mSequence; }
148 
149     /**
150      * This method sets the MPL Sequence value.
151      *
152      * @param[in]  aSequence  The MPL Sequence value.
153      *
154      */
SetSequence(uint8_t aSequence)155     void SetSequence(uint8_t aSequence) { mSequence = aSequence; }
156 
157     /**
158      * This method returns the MPL Seed Id value.
159      *
160      * @returns The MPL Seed Id value.
161      *
162      */
GetSeedId(void) const163     uint16_t GetSeedId(void) const { return HostSwap16(mSeedId); }
164 
165     /**
166      * This method sets the MPL Seed Id value.
167      *
168      * @param[in]  aSeedId  The MPL Seed Id value.
169      *
170      */
SetSeedId(uint16_t aSeedId)171     void SetSeedId(uint16_t aSeedId) { mSeedId = HostSwap16(aSeedId); }
172 
173 private:
174     static constexpr uint8_t kSeedIdLengthMask = 3 << 6;
175     static constexpr uint8_t kMaxFlag          = 1 << 5;
176 
177     uint8_t  mControl;
178     uint8_t  mSequence;
179     uint16_t mSeedId;
180 } OT_TOOL_PACKED_END;
181 
182 /**
183  * This class implements MPL message processing.
184  *
185  */
186 class Mpl : public InstanceLocator, private NonCopyable
187 {
188 public:
189     /**
190      * This constructor initializes the MPL object.
191      *
192      * @param[in]  aInstance  A reference to the OpenThread instance.
193      *
194      */
195     explicit Mpl(Instance &aInstance);
196 
197     /**
198      * This method initializes the MPL option.
199      *
200      * @param[in]  aOption   A reference to the MPL header to initialize.
201      * @param[in]  aAddress  A reference to the IPv6 Source Address.
202      *
203      */
204     void InitOption(OptionMpl &aOption, const Address &aAddress);
205 
206     /**
207      * This method processes an MPL option. When the MPL module acts as an MPL Forwarder
208      * it disseminates MPL Data Message using Trickle timer expirations. When acts as an
209      * MPL Seed it allows to send the first MPL Data Message directly, then sets up Trickle
210      * timer expirations for subsequent retransmissions.
211      *
212      * @param[in]  aMessage    A reference to the message.
213      * @param[in]  aAddress    A reference to the IPv6 Source Address.
214      * @param[in]  aIsOutbound TRUE if this message was locally generated, FALSE otherwise.
215      * @param[out] aReceive    Set to FALSE if the MPL message is a duplicate and must not
216      *                         go through the receiving process again, untouched otherwise.
217      *
218      * @retval kErrorNone  Successfully processed the MPL option.
219      * @retval kErrorDrop  The MPL message is a duplicate and should be dropped.
220      *
221      */
222     Error ProcessOption(Message &aMessage, const Address &aAddress, bool aIsOutbound, bool &aReceive);
223 
224     /**
225      * This method returns the MPL Seed Id value.
226      *
227      * @returns The MPL Seed Id value.
228      *
229      */
GetSeedId(void) const230     uint16_t GetSeedId(void) const { return mSeedId; }
231 
232     /**
233      * This method sets the MPL Seed Id value.
234      *
235      * @param[in]  aSeedId  The MPL Seed Id value.
236      *
237      */
SetSeedId(uint16_t aSeedId)238     void SetSeedId(uint16_t aSeedId) { mSeedId = aSeedId; }
239 
240     /**
241      * This method sets the IPv6 matching address, that allows to elide MPL Seed Id.
242      *
243      * @param[in] aAddress The reference to the IPv6 matching address.
244      *
245      */
SetMatchingAddress(const Address & aAddress)246     void SetMatchingAddress(const Address &aAddress) { mMatchingAddress = &aAddress; }
247 
248 #if OPENTHREAD_FTD
249     /**
250      * This method gets the MPL number of Trickle timer expirations that occur before
251      * terminating the Trickle algorithm's retransmission of a given MPL Data Message.
252      *
253      * @returns The MPL number of Trickle timer expirations.
254      *
255      */
GetTimerExpirations(void) const256     uint8_t GetTimerExpirations(void) const { return mTimerExpirations; }
257 
258     /**
259      * This method sets the MPL number of Trickle timer expirations that occur before
260      * terminating the Trickle algorithm's retransmission of a given MPL Data Message.
261      *
262      * @param[in]  aTimerExpirations  The number of Trickle timer expirations.
263      *
264      */
SetTimerExpirations(uint8_t aTimerExpirations)265     void SetTimerExpirations(uint8_t aTimerExpirations) { mTimerExpirations = aTimerExpirations; }
266 
267     /**
268      * This method returns a reference to the buffered message set.
269      *
270      * @returns A reference to the buffered message set.
271      *
272      */
GetBufferedMessageSet(void) const273     const MessageQueue &GetBufferedMessageSet(void) const { return mBufferedMessageSet; }
274 #endif // OPENTHREAD_FTD
275 
276 private:
277     static constexpr uint16_t kNumSeedEntries      = OPENTHREAD_CONFIG_MPL_SEED_SET_ENTRIES;
278     static constexpr uint32_t kSeedEntryLifetime   = OPENTHREAD_CONFIG_MPL_SEED_SET_ENTRY_LIFETIME;
279     static constexpr uint32_t kSeedEntryLifetimeDt = 1000;
280     static constexpr uint8_t  kDataMessageInterval = 64;
281 
282     struct SeedEntry
283     {
284         uint16_t mSeedId;
285         uint8_t  mSequence;
286         uint8_t  mLifetime;
287     };
288 
289     static void HandleSeedSetTimer(Timer &aTimer);
290     void        HandleSeedSetTimer(void);
291 
292     Error UpdateSeedSet(uint16_t aSeedId, uint8_t aSequence);
293 
294     SeedEntry      mSeedSet[kNumSeedEntries];
295     const Address *mMatchingAddress;
296     TimerMilli     mSeedSetTimer;
297     uint16_t       mSeedId;
298     uint8_t        mSequence;
299 
300 #if OPENTHREAD_FTD
301     struct Metadata
302     {
AppendToot::Ip6::Mpl::Metadata303         Error AppendTo(Message &aMessage) const { return aMessage.Append(*this); }
304         void  ReadFrom(const Message &aMessage);
305         void  RemoveFrom(Message &aMessage) const;
306         void  UpdateIn(Message &aMessage) const;
307         void  GenerateNextTransmissionTime(TimeMilli aCurrentTime, uint8_t aInterval);
308 
309         TimeMilli mTransmissionTime;
310         uint16_t  mSeedId;
311         uint8_t   mSequence;
312         uint8_t   mTransmissionCount;
313         uint8_t   mIntervalOffset;
314     };
315 
316     static void HandleRetransmissionTimer(Timer &aTimer);
317     void        HandleRetransmissionTimer(void);
318 
319     void AddBufferedMessage(Message &aMessage, uint16_t aSeedId, uint8_t aSequence, bool aIsOutbound);
320 
321     MessageQueue mBufferedMessageSet;
322     TimerMilli   mRetransmissionTimer;
323     uint8_t      mTimerExpirations;
324 #endif // OPENTHREAD_FTD
325 };
326 
327 /**
328  * @}
329  *
330  */
331 
332 } // namespace Ip6
333 } // namespace ot
334 
335 #endif // IP6_MPL_HPP_
336