Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / inet / tests / TestInetLayerCommon.cpp
1 /*
2  *
3  *    Copyright (c) 2020-2021 Project CHIP Authors
4  *    Copyright (c) 2019 Google LLC
5  *    All rights reserved.
6  *
7  *    Licensed under the Apache License, Version 2.0 (the "License");
8  *    you may not use this file except in compliance with the License.
9  *    You may obtain a copy of the License at
10  *
11  *        http://www.apache.org/licenses/LICENSE-2.0
12  *
13  *    Unless required by applicable law or agreed to in writing, software
14  *    distributed under the License is distributed on an "AS IS" BASIS,
15  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  *    See the License for the specific language governing permissions and
17  *    limitations under the License.
18  */
19
20 /**
21  *    @file
22  *      This file defines common preprocessor defintions, constants,
23  *      functions, and globals for unit and functional tests for the
24  *      Inet layer.
25  *
26  */
27
28 #include "TestInetLayerCommon.hpp"
29
30 #include <stdlib.h>
31 #include <string.h>
32 #include <utility>
33
34 #include <nlbyteorder.hpp>
35
36 #include <inet/InetLayer.h>
37
38 #include <support/CodeUtils.h>
39
40 #include "TestInetCommon.h"
41
42 using namespace ::chip;
43 using namespace ::chip::Inet;
44 using namespace ::chip::System;
45
46 // Type Definitions
47
48 struct ICMPEchoHeader
49 {
50     uint8_t mType;
51     uint8_t mCode;
52     uint16_t mChecksum;
53     uint16_t mID;
54     uint16_t mSequenceNumber;
55 } __attribute__((packed));
56
57 typedef struct ICMPEchoHeader ICMPv4EchoHeader;
58 typedef struct ICMPEchoHeader ICMPv6EchoHeader;
59
60 // Global Variables
61
62 static const uint8_t kICMPv4_EchoRequest = 8;
63 static const uint8_t kICMPv4_EchoReply   = 0;
64
65 static const uint8_t kICMPv6_EchoRequest = 128;
66 static const uint8_t kICMPv6_EchoReply   = 129;
67
68 // clang-format off
69 const uint8_t            gICMPv4Types[kICMPv4_FilterTypes] =
70 {
71     kICMPv4_EchoRequest,
72     kICMPv4_EchoReply
73 };
74
75 const uint8_t            gICMPv6Types[kICMPv6_FilterTypes] =
76 {
77     kICMPv6_EchoRequest,
78     kICMPv6_EchoReply
79 };
80 // clang-format on
81
82 bool gSendIntervalExpired = true;
83
84 uint32_t gSendIntervalMs = 1000;
85
86 const char * gInterfaceName = nullptr;
87
88 InterfaceId gInterfaceId = INET_NULL_INTERFACEID;
89
90 uint16_t gSendSize = 59;
91
92 uint32_t gOptFlags = 0;
93
94 namespace Common {
95
96 bool IsReceiver()
97 {
98     return ((gOptFlags & kOptFlagListen) == kOptFlagListen);
99 }
100
101 bool IsSender()
102 {
103     return (!IsReceiver());
104 }
105
106 bool IsTesting(const TestStatus & aTestStatus)
107 {
108     bool lStatus;
109
110     lStatus = (!aTestStatus.mFailed && !aTestStatus.mSucceeded);
111
112     return (lStatus);
113 }
114
115 bool WasSuccessful(const TestStatus & aTestStatus)
116 {
117     bool lStatus = false;
118
119     if (aTestStatus.mFailed)
120         lStatus = false;
121     else if (aTestStatus.mSucceeded)
122         lStatus = true;
123
124     return (lStatus);
125 }
126
127 static void FillDataBufferPattern(uint8_t * aBuffer, uint16_t aLength, uint16_t aPatternStartOffset, uint8_t aFirstValue)
128 {
129     for (uint16_t i = aPatternStartOffset; i < aLength; i++)
130     {
131         const uint8_t lValue = static_cast<uint8_t>(aFirstValue & 0xFF);
132
133         aBuffer[i] = lValue;
134
135         aFirstValue++;
136     }
137 }
138
139 static bool CheckDataBufferPattern(const uint8_t * aBuffer, uint16_t aLength, uint16_t aPatternStartOffset, uint8_t aFirstValue)
140 {
141     bool lStatus = true;
142
143     for (uint16_t i = aPatternStartOffset; i < aLength; i++)
144     {
145         const uint8_t lValue = aBuffer[i];
146
147         // clang-format off
148         VerifyOrExit(lValue == static_cast<uint8_t>(aFirstValue),
149                      printf("Bad data value at offset %u (0x%04x): "
150                             "expected 0x%02x, found 0x%02x\n",
151                             i, i, aFirstValue, lValue);
152                      lStatus = false;
153                      DumpMemory(aBuffer + aPatternStartOffset,
154                                 aLength - aPatternStartOffset,
155                                 "0x",
156                                 16));
157         // clang-format on
158
159         aFirstValue++;
160     }
161
162 exit:
163     return (lStatus);
164 }
165
166 static PacketBufferHandle MakeDataBuffer(uint16_t aDesiredLength, uint16_t aPatternStartOffset, uint8_t aFirstValue)
167 {
168     PacketBufferHandle lBuffer;
169
170     VerifyOrExit(aPatternStartOffset <= aDesiredLength, );
171
172     lBuffer = PacketBufferHandle::New(aDesiredLength);
173     VerifyOrExit(!lBuffer.IsNull(), );
174
175     aDesiredLength = min(lBuffer->MaxDataLength(), aDesiredLength);
176
177     FillDataBufferPattern(lBuffer->Start(), aDesiredLength, aPatternStartOffset, aFirstValue);
178
179     lBuffer->SetDataLength(aDesiredLength);
180
181 exit:
182     return lBuffer;
183 }
184
185 static PacketBufferHandle MakeDataBuffer(uint16_t aDesiredLength, uint16_t aPatternStartOffset)
186 {
187     constexpr uint8_t lFirstValue = 0;
188     PacketBufferHandle lBuffer    = MakeDataBuffer(aDesiredLength, aPatternStartOffset, lFirstValue);
189     VerifyOrExit(!lBuffer.IsNull(), );
190
191 exit:
192     return (lBuffer);
193 }
194
195 template <typename tType>
196 static PacketBufferHandle MakeICMPDataBuffer(uint16_t aDesiredUserLength, uint16_t aHeaderLength, uint16_t aPatternStartOffset,
197                                              uint8_t aType)
198 {
199     static uint16_t lSequenceNumber = 0;
200     PacketBufferHandle lBuffer;
201
202     // To ensure there is enough room for the user data and the ICMP
203     // header, include both the user data size and the ICMP header length.
204
205     lBuffer = MakeDataBuffer(static_cast<uint16_t>(aDesiredUserLength + aHeaderLength), aPatternStartOffset);
206
207     if (!lBuffer.IsNull())
208     {
209         tType * lHeader = reinterpret_cast<tType *>(lBuffer->Start());
210
211         lHeader->mType           = aType;
212         lHeader->mCode           = 0;
213         lHeader->mChecksum       = 0;
214         lHeader->mID             = static_cast<uint16_t>(rand() & UINT16_MAX);
215         lHeader->mSequenceNumber = nlByteOrderSwap16HostToBig(lSequenceNumber++);
216     }
217
218     return (lBuffer);
219 }
220
221 PacketBufferHandle MakeICMPv4DataBuffer(uint16_t aDesiredUserLength)
222 {
223     constexpr uint16_t lICMPHeaderLength   = sizeof(ICMPv4EchoHeader);
224     constexpr uint16_t lPatternStartOffset = lICMPHeaderLength;
225     const uint8_t lType                    = gICMPv4Types[kICMP_EchoRequestIndex];
226
227     return MakeICMPDataBuffer<ICMPv4EchoHeader>(aDesiredUserLength, lICMPHeaderLength, lPatternStartOffset, lType);
228 }
229
230 PacketBufferHandle MakeICMPv6DataBuffer(uint16_t aDesiredUserLength)
231 {
232     constexpr uint16_t lICMPHeaderLength   = sizeof(ICMPv6EchoHeader);
233     constexpr uint16_t lPatternStartOffset = lICMPHeaderLength;
234     const uint8_t lType                    = gICMPv6Types[kICMP_EchoRequestIndex];
235
236     return MakeICMPDataBuffer<ICMPv6EchoHeader>(aDesiredUserLength, lICMPHeaderLength, lPatternStartOffset, lType);
237 }
238
239 PacketBufferHandle MakeDataBuffer(uint16_t aDesiredLength, uint8_t aFirstValue)
240 {
241     constexpr uint16_t lPatternStartOffset = 0;
242     return MakeDataBuffer(aDesiredLength, lPatternStartOffset, aFirstValue);
243 }
244
245 PacketBufferHandle MakeDataBuffer(uint16_t aDesiredLength)
246 {
247     constexpr uint16_t lPatternStartOffset = 0;
248     return MakeDataBuffer(aDesiredLength, lPatternStartOffset);
249 }
250
251 static bool HandleDataReceived(const PacketBufferHandle & aBuffer, TransferStats & aStats, bool aStatsByPacket, bool aCheckBuffer,
252                                uint16_t aPatternStartOffset, uint8_t aFirstValue)
253 {
254     bool lStatus              = true;
255     uint16_t lTotalDataLength = 0;
256
257     // Walk through each buffer in the packet chain, checking the
258     // buffer for the expected pattern, if requested.
259
260     for (PacketBufferHandle lBuffer = aBuffer.Retain(); !lBuffer.IsNull(); lBuffer.Advance())
261     {
262         const uint16_t lDataLength = lBuffer->DataLength();
263
264         if (aCheckBuffer)
265         {
266             const uint8_t * p = lBuffer->Start();
267
268             lStatus = CheckDataBufferPattern(p, lDataLength, aPatternStartOffset, aFirstValue);
269             VerifyOrExit(lStatus == true, );
270         }
271
272         lTotalDataLength = static_cast<uint16_t>(lTotalDataLength + lBuffer->DataLength());
273         aFirstValue      = static_cast<uint8_t>(aFirstValue + lBuffer->DataLength());
274     }
275
276     // If we are accumulating stats by packet rather than by size,
277     // then increment by one (1) rather than the total buffer length.
278
279     aStats.mReceive.mActual += ((aStatsByPacket) ? 1 : lTotalDataLength);
280
281 exit:
282     return (lStatus);
283 }
284
285 static bool HandleICMPDataReceived(PacketBufferHandle aBuffer, uint16_t aHeaderLength, TransferStats & aStats, bool aStatsByPacket,
286                                    bool aCheckBuffer)
287 {
288     const uint16_t lPatternStartOffset = 0;
289     bool lStatus;
290
291     aBuffer->ConsumeHead(aHeaderLength);
292
293     lStatus = HandleDataReceived(aBuffer, aStats, aStatsByPacket, aCheckBuffer, lPatternStartOffset);
294
295     return (lStatus);
296 }
297
298 bool HandleICMPv4DataReceived(PacketBufferHandle && aBuffer, TransferStats & aStats, bool aStatsByPacket, bool aCheckBuffer)
299 {
300     const uint16_t lICMPHeaderLength = sizeof(ICMPv4EchoHeader);
301     bool lStatus;
302
303     lStatus = HandleICMPDataReceived(std::move(aBuffer), lICMPHeaderLength, aStats, aStatsByPacket, aCheckBuffer);
304
305     return (lStatus);
306 }
307
308 bool HandleICMPv6DataReceived(PacketBufferHandle && aBuffer, TransferStats & aStats, bool aStatsByPacket, bool aCheckBuffer)
309 {
310     const uint16_t lICMPHeaderLength = sizeof(ICMPv6EchoHeader);
311     bool lStatus;
312
313     lStatus = HandleICMPDataReceived(std::move(aBuffer), lICMPHeaderLength, aStats, aStatsByPacket, aCheckBuffer);
314
315     return (lStatus);
316 }
317
318 bool HandleDataReceived(const PacketBufferHandle & aBuffer, TransferStats & aStats, bool aStatsByPacket, bool aCheckBuffer,
319                         uint8_t aFirstValue)
320 {
321     const uint16_t lPatternStartOffset = 0;
322     bool lStatus;
323
324     lStatus = HandleDataReceived(aBuffer, aStats, aStatsByPacket, aCheckBuffer, lPatternStartOffset, aFirstValue);
325
326     return (lStatus);
327 }
328
329 bool HandleDataReceived(const PacketBufferHandle & aBuffer, TransferStats & aStats, bool aStatsByPacket, bool aCheckBuffer)
330 {
331     const uint8_t lFirstValue          = 0;
332     const uint16_t lPatternStartOffset = 0;
333     bool lStatus;
334
335     lStatus = HandleDataReceived(aBuffer, aStats, aStatsByPacket, aCheckBuffer, lPatternStartOffset, lFirstValue);
336
337     return (lStatus);
338 }
339
340 bool HandleUDPDataReceived(const PacketBufferHandle & aBuffer, TransferStats & aStats, bool aStatsByPacket, bool aCheckBuffer)
341 {
342     bool lStatus;
343
344     lStatus = HandleDataReceived(aBuffer, aStats, aStatsByPacket, aCheckBuffer);
345
346     return (lStatus);
347 }
348
349 bool HandleTCPDataReceived(const PacketBufferHandle & aBuffer, TransferStats & aStats, bool aStatsByPacket, bool aCheckBuffer)
350 {
351     bool lStatus;
352
353     lStatus = HandleDataReceived(aBuffer, aStats, aStatsByPacket, aCheckBuffer);
354
355     return (lStatus);
356 }
357
358 // Timer Callback Handler
359
360 void HandleSendTimerComplete(System::Layer * aSystemLayer, void * aAppState, System::Error aError)
361 {
362     INET_FAIL_ERROR(aError, "Send timer completed with error");
363
364     gSendIntervalExpired = true;
365
366     DriveSend();
367 }
368
369 // Raw Endpoint Callback Handlers
370
371 void HandleRawMessageReceived(const IPEndPointBasis * aEndPoint, const PacketBufferHandle & aBuffer,
372                               const IPPacketInfo * aPacketInfo)
373 {
374     char lSourceAddressBuffer[INET6_ADDRSTRLEN];
375     char lDestinationAddressBuffer[INET6_ADDRSTRLEN];
376
377     aPacketInfo->SrcAddress.ToString(lSourceAddressBuffer);
378     aPacketInfo->DestAddress.ToString(lDestinationAddressBuffer);
379
380     printf("Raw message received from %s to %s (%zu bytes)\n", lSourceAddressBuffer, lDestinationAddressBuffer,
381            static_cast<size_t>(aBuffer->DataLength()));
382 }
383
384 void HandleRawReceiveError(const IPEndPointBasis * aEndPoint, const INET_ERROR & aError, const IPPacketInfo * aPacketInfo)
385 {
386     char lAddressBuffer[INET6_ADDRSTRLEN];
387
388     if (aPacketInfo != nullptr)
389     {
390         aPacketInfo->SrcAddress.ToString(lAddressBuffer);
391     }
392     else
393     {
394         strcpy(lAddressBuffer, "(unknown)");
395     }
396
397     printf("IP receive error from %s %s\n", lAddressBuffer, ErrorStr(aError));
398 }
399
400 // UDP Endpoint Callback Handlers
401
402 void HandleUDPMessageReceived(const IPEndPointBasis * aEndPoint, const PacketBufferHandle & aBuffer,
403                               const IPPacketInfo * aPacketInfo)
404 {
405     char lSourceAddressBuffer[INET6_ADDRSTRLEN];
406     char lDestinationAddressBuffer[INET6_ADDRSTRLEN];
407
408     aPacketInfo->SrcAddress.ToString(lSourceAddressBuffer);
409     aPacketInfo->DestAddress.ToString(lDestinationAddressBuffer);
410
411     printf("UDP packet received from %s:%u to %s:%u (%zu bytes)\n", lSourceAddressBuffer, aPacketInfo->SrcPort,
412            lDestinationAddressBuffer, aPacketInfo->DestPort, static_cast<size_t>(aBuffer->DataLength()));
413 }
414
415 void HandleUDPReceiveError(const IPEndPointBasis * aEndPoint, const INET_ERROR & aError, const IPPacketInfo * aPacketInfo)
416 {
417     char lAddressBuffer[INET6_ADDRSTRLEN];
418     uint16_t lSourcePort;
419
420     if (aPacketInfo != nullptr)
421     {
422         aPacketInfo->SrcAddress.ToString(lAddressBuffer);
423         lSourcePort = aPacketInfo->SrcPort;
424     }
425     else
426     {
427         strcpy(lAddressBuffer, "(unknown)");
428         lSourcePort = 0;
429     }
430
431     printf("UDP receive error from %s:%u: %s\n", lAddressBuffer, lSourcePort, ErrorStr(aError));
432 }
433
434 } // namespace Common