3 * Copyright (c) 2020 Project CHIP Authors
4 * Copyright (c) 2013-2018 Nest Labs, Inc.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
21 * This file implements constants, globals and interfaces common to
22 * and used by all CHP Inet layer library test applications and
25 * NOTE: These do not comprise a public part of the CHIP API and
26 * are subject to change without notice.
30 #ifndef __STDC_LIMIT_MACROS
31 #define __STDC_LIMIT_MACROS
33 #ifndef __STDC_FORMAT_MACROS
34 #define __STDC_FORMAT_MACROS
37 #include "TestInetCommon.h"
45 #include <sys/types.h>
48 #include <inet/InetFaultInjection.h>
49 #include <support/CHIPFaultInjection.h>
50 #include <support/CHIPMem.h>
51 #include <support/ScopedBuffer.h>
52 #include <system/SystemFaultInjection.h>
53 #include <system/SystemTimer.h>
55 #if CHIP_SYSTEM_CONFIG_USE_LWIP
57 #include <lwip/init.h>
58 #include <lwip/netif.h>
60 #include <lwip/tcpip.h>
61 #include <netif/etharp.h>
63 #if CHIP_TARGET_STYLE_UNIX
65 // TapAddrAutoconf and TapInterface are only needed for LwIP on
66 // sockets simulation in which a host tap/tun interface is used to
67 // proxy the LwIP stack onto a host native network interface.
69 #include "TapAddrAutoconf.h"
70 #include "TapInterface.h"
71 #endif // CHIP_TARGET_STYLE_UNIX
72 #endif // CHIP_SYSTEM_CONFIG_USE_LWIP
74 #if CHIP_SYSTEM_CONFIG_USE_SOCKETS
75 #include <arpa/inet.h>
76 #include <sys/select.h>
77 #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS
80 using namespace chip::Inet;
82 #if CHIP_SYSTEM_CONFIG_USE_LWIP
83 static sys_mbox_t * sLwIPEventQueue = NULL;
84 static unsigned int sLwIPAcquireCount = 0;
86 static void AcquireLwIP(void)
88 if (sLwIPAcquireCount++ == 0)
90 sys_mbox_new(sLwIPEventQueue, 100);
94 static void ReleaseLwIP(void)
96 #if !(LWIP_VERSION_MAJOR >= 2 && LWIP_VERSION_MINOR >= 1)
97 if (sLwIPAcquireCount > 0 && --sLwIPAcquireCount == 0)
99 tcpip_finish(NULL, NULL);
103 #endif // CHIP_SYSTEM_CONFIG_USE_LWIP
105 struct RestartCallbackContext
111 static void RebootCallbackFn();
112 static void PostInjectionCallbackFn(nl::FaultInjection::Manager * aManager, nl::FaultInjection::Identifier aId,
113 nl::FaultInjection::Record * aFaultRecord);
115 static struct RestartCallbackContext sRestartCallbackCtx;
116 static nl::FaultInjection::Callback sFuzzECHeaderCb;
117 static nl::FaultInjection::Callback sAsyncEventCb;
120 static nl::FaultInjection::GlobalContext sFaultInjectionGlobalContext = {
123 PostInjectionCallbackFn
128 System::Layer gSystemLayer;
130 Inet::InetLayer gInet;
132 #if CHIP_SYSTEM_CONFIG_USE_LWIP && !CHIP_SYSTEM_CONFIG_USE_SOCKETS
133 #if CHIP_TARGET_STYLE_UNIX
134 // TapAddrAutoconf and TapInterface are only needed for LwIP on
135 // sockets simulation in which a host tap/tun interface is used to
136 // proxy the LwIP stack onto a host native network interface.
137 // CollectTapAddresses() is only available on such targets.
139 static std::vector<TapInterface> sTapIFs;
140 #endif // CHIP_TARGET_STYLE_UNIX
141 static std::vector<struct netif> sNetIFs; // interface to filter
142 #endif // CHIP_SYSTEM_CONFIG_USE_LWIP && !CHIP_SYSTEM_CONFIG_USE_SOCKETS
144 #if CHIP_SYSTEM_CONFIG_USE_LWIP
146 static bool NetworkIsReady();
147 static void OnLwIPInitComplete(void * arg);
148 #endif // CHIP_SYSTEM_CONFIG_USE_LWIP
150 char gDefaultTapDeviceName[32];
152 bool gSigusr1Received = false;
154 static void UseStdoutLineBuffering()
156 // Set stdout to be line buffered with a buffer of 512 (will flush on new line
157 // or when the buffer of 512 is exceeded).
158 #if CHIP_CONFIG_MEMORY_MGMT_MALLOC
159 constexpr char * buf = nullptr;
161 static char buf[512];
162 #endif // CHIP_CONFIG_MEMORY_MGMT_MALLOC
163 setvbuf(stdout, buf, _IOLBF, 512);
166 void InitTestInetCommon()
168 chip::Platform::MemoryInit();
169 UseStdoutLineBuffering();
172 static void ExitOnSIGUSR1Handler(int signum)
174 // exit() allows us a slightly better clean up (gcov data) than SIGINT's exit
178 // We set a hook to exit when we receive SIGUSR1, SIGTERM or SIGHUP
179 void SetSIGUSR1Handler()
181 SetSignalHandler(ExitOnSIGUSR1Handler);
184 void SetSignalHandler(SignalHandler handler)
187 int signals[] = { SIGUSR1 };
190 memset(&sa, 0, sizeof(sa));
191 sa.sa_handler = handler;
193 for (i = 0; i < sizeof(signals) / sizeof(signals[0]); i++)
195 if (sigaction(signals[i], &sa, nullptr) == -1)
197 perror("Can't catch signal");
203 void InitSystemLayer()
205 #if CHIP_SYSTEM_CONFIG_USE_LWIP
208 gSystemLayer.Init(sLwIPEventQueue);
209 #else // !CHIP_SYSTEM_CONFIG_USE_LWIP
210 gSystemLayer.Init(nullptr);
211 #endif // !CHIP_SYSTEM_CONFIG_USE_LWIP
214 void ShutdownSystemLayer()
216 gSystemLayer.Shutdown();
218 #if CHIP_SYSTEM_CONFIG_USE_LWIP
220 #endif // CHIP_SYSTEM_CONFIG_USE_LWIP
223 #if CHIP_SYSTEM_CONFIG_USE_LWIP
224 static void PrintNetworkState()
228 for (size_t j = 0; j < gNetworkOptions.TapDeviceName.size(); j++)
230 struct netif * netIF = &(sNetIFs[j]);
231 #if CHIP_TARGET_STYLE_UNIX
232 // TapAddrAutoconf and TapInterface are only needed for LwIP on
233 // sockets simulation in which a host tap/tun interface is used to
234 // proxy the LwIP stack onto a host native network interface.
235 // CollectTapAddresses() is only available on such targets.
237 TapInterface * tapIF = &(sTapIFs[j]);
238 #endif // CHIP_TARGET_STYLE_UNIX
239 GetInterfaceName(netIF, intfName, sizeof(intfName));
241 printf("LwIP interface ready\n");
242 printf(" Interface Name: %s\n", intfName);
243 printf(" Tap Device: %s\n", gNetworkOptions.TapDeviceName[j]);
244 #if CHIP_TARGET_STYLE_UNIX
245 // TapAddrAutoconf and TapInterface are only needed for LwIP on
246 // sockets simulation in which a host tap/tun interface is used to
247 // proxy the LwIP stack onto a host native network interface.
248 // CollectTapAddresses() is only available on such targets.
250 printf(" MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n", tapIF->macAddr[0], tapIF->macAddr[1], tapIF->macAddr[2],
251 tapIF->macAddr[3], tapIF->macAddr[4], tapIF->macAddr[5]);
252 #endif // CHIP_TARGET_STYLE_UNIX
254 #if INET_CONFIG_ENABLE_IPV4
255 printf(" IPv4 Address: %s\n", ipaddr_ntoa(&(netIF->ip_addr)));
256 printf(" IPv4 Mask: %s\n", ipaddr_ntoa(&(netIF->netmask)));
257 printf(" IPv4 Gateway: %s\n", ipaddr_ntoa(&(netIF->gw)));
258 #endif // INET_CONFIG_ENABLE_IPV4
259 for (int i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++)
261 if (!ip6_addr_isany(netif_ip6_addr(netIF, i)))
263 printf(" IPv6 address: %s, 0x%02x\n", ip6addr_ntoa(netif_ip6_addr(netIF, i)), netif_ip6_addr_state(netIF, i));
267 #if INET_CONFIG_ENABLE_DNS_RESOLVER
268 char dnsServerAddrStr[DNS_MAX_NAME_LENGTH];
269 printf(" DNS Server: %s\n", gNetworkOptions.DNSServerAddr.ToString(dnsServerAddrStr, sizeof(dnsServerAddrStr)));
270 #endif // INET_CONFIG_ENABLE_DNS_RESOLVER
272 #endif // CHIP_SYSTEM_CONFIG_USE_LWIP
276 void * lContext = nullptr;
278 #if CHIP_SYSTEM_CONFIG_USE_LWIP
279 #if CHIP_SYSTEM_CONFIG_USE_SOCKETS
281 tcpip_init(NULL, NULL);
283 #else // !CHIP_SYSTEM_CONFIG_USE_SOCKETS
285 // If an tap device name hasn't been specified, derive one from the IPv6 interface id.
287 if (gNetworkOptions.TapDeviceName.empty())
289 for (size_t j = 0; j < gNetworkOptions.LocalIPv6Addr.size(); j++)
291 uint64_t iid = gNetworkOptions.LocalIPv6Addr[j].InterfaceId();
292 char * tap_name = (char *) chip::Platform::MemoryAlloc(sizeof(gDefaultTapDeviceName));
294 snprintf(tap_name, sizeof(gDefaultTapDeviceName), "chip-dev-%" PRIx64, iid & 0xFFFF);
295 gNetworkOptions.TapDeviceName.push_back(tap_name);
299 #if CHIP_TARGET_STYLE_UNIX
300 // TapAddrAutoconf and TapInterface are only needed for LwIP on
301 // sockets simulation in which a host tap/tun interface is used to
302 // proxy the LwIP stack onto a host native network interface.
303 // CollectTapAddresses() is only available on such targets.
306 #endif // CHIP_TARGET_STYLE_UNIX
309 for (size_t j = 0; j < gNetworkOptions.TapDeviceName.size(); j++)
311 #if CHIP_TARGET_STYLE_UNIX
312 // TapAddrAutoconf and TapInterface are only needed for LwIP on
313 // sockets simulation in which a host tap/tun interface is used to
314 // proxy the LwIP stack onto a host native network interface.
315 // CollectTapAddresses() is only available on such targets.
318 sTapIFs.push_back(tapIF);
319 #endif // CHIP_TARGET_STYLE_UNIX
321 sNetIFs.push_back(netIF);
324 #if CHIP_TARGET_STYLE_UNIX
326 // TapAddrAutoconf and TapInterface are only needed for LwIP on
327 // sockets simulation in which a host tap/tun interface is used to
328 // proxy the LwIP stack onto a host native network interface.
329 // CollectTapAddresses() is only available on such targets.
333 for (size_t j = 0; j < gNetworkOptions.TapDeviceName.size(); j++)
335 lwipErr = TapInterface_Init(&(sTapIFs[j]), gNetworkOptions.TapDeviceName[j], NULL);
336 if (lwipErr != ERR_OK)
338 printf("Failed to initialize tap device %s: %s\n", gNetworkOptions.TapDeviceName[j],
339 ErrorStr(System::MapErrorLwIP(lwipErr)));
343 #endif // CHIP_TARGET_STYLE_UNIX
344 tcpip_init(OnLwIPInitComplete, NULL);
349 for (size_t j = 0; j < gNetworkOptions.TapDeviceName.size(); j++)
351 std::vector<char *> addrsVec;
355 #if CHIP_TARGET_STYLE_UNIX
357 // TapAddrAutoconf and TapInterface are only needed for LwIP on
358 // sockets simulation in which a host tap/tun interface is used to
359 // proxy the LwIP stack onto a host native network interface.
360 // CollectTapAddresses() is only available on such targets.
361 if (gNetworkOptions.TapUseSystemConfig)
363 CollectTapAddresses(addrsVec, gNetworkOptions.TapDeviceName[j]);
365 #endif // CHIP_TARGET_STYLE_UNIX
366 #if INET_CONFIG_ENABLE_IPV4
368 IPAddress ip4Addr = (j < gNetworkOptions.LocalIPv4Addr.size()) ? gNetworkOptions.LocalIPv4Addr[j] : IPAddress::Any;
369 for (size_t n = 0; n < addrsVec.size(); n++)
372 if (IPAddress::FromString(addrsVec[n], auto_addr) && auto_addr.IsIPv4())
378 #if CHIP_TARGET_STYLE_UNIX
379 // TapAddrAutoconf and TapInterface are only needed for LwIP on
380 // sockets simulation in which a host tap/tun interface is used to
381 // proxy the LwIP stack onto a host native network interface.
382 // CollectTapAddresses() is only available on such targets.
384 IPAddress ip4Gateway = (j < gNetworkOptions.IPv4GatewayAddr.size()) ? gNetworkOptions.IPv4GatewayAddr[j] : IPAddress::Any;
387 #if LWIP_VERSION_MAJOR > 1
388 ip4_addr_t ip4AddrLwIP, ip4NetmaskLwIP, ip4GatewayLwIP;
389 #else // LWIP_VERSION_MAJOR <= 1
390 ip_addr_t ip4AddrLwIP, ip4NetmaskLwIP, ip4GatewayLwIP;
391 #endif // LWIP_VERSION_MAJOR <= 1
393 ip4AddrLwIP = ip4Addr.ToIPv4();
394 IP4_ADDR(&ip4NetmaskLwIP, 255, 255, 255, 0);
395 ip4GatewayLwIP = ip4Gateway.ToIPv4();
396 netif_add(&(sNetIFs[j]), &ip4AddrLwIP, &ip4NetmaskLwIP, &ip4GatewayLwIP, &(sTapIFs[j]), TapInterface_SetupNetif,
399 #endif // CHIP_TARGET_STYLE_UNIX
401 #endif // INET_CONFIG_ENABLE_IPV4
403 netif_create_ip6_linklocal_address(&(sNetIFs[j]), 1);
405 #if !(LWIP_VERSION_MAJOR >= 2 && LWIP_VERSION_MINOR >= 1)
406 if (j < gNetworkOptions.LocalIPv6Addr.size())
408 ip6_addr_t ip6addr = gNetworkOptions.LocalIPv6Addr[j].ToIPv6();
410 netif_add_ip6_address_with_route(&(sNetIFs[j]), &ip6addr, 64, &index);
411 // add ipv6 route for ipv6 address
412 if (j < gNetworkOptions.IPv6GatewayAddr.size())
414 static ip6_addr_t br_ip6_addr = gNetworkOptions.IPv6GatewayAddr[j].ToIPv6();
415 struct ip6_prefix ip6_prefix;
416 ip6_prefix.addr = Inet::IPAddress::Any.ToIPv6();
417 ip6_prefix.prefix_len = 0;
418 ip6_add_route_entry(&ip6_prefix, &sNetIFs[j], &br_ip6_addr, NULL);
422 netif_ip6_addr_set_state(&(sNetIFs[j]), index, IP6_ADDR_PREFERRED);
425 for (size_t n = 0; n < addrsVec.size(); n++)
428 if (IPAddress::FromString(addrsVec[n], auto_addr) && !auto_addr.IsIPv4())
430 ip6_addr_t ip6addr = auto_addr.ToIPv6();
432 if (auto_addr.IsIPv6LinkLocal())
433 continue; // skip over the LLA addresses, LwIP is aready adding those
434 if (auto_addr.IsIPv6Multicast())
435 continue; // skip over the multicast addresses from host for now.
436 netif_add_ip6_address_with_route(&(sNetIFs[j]), &ip6addr, 64, &index);
439 netif_ip6_addr_set_state(&(sNetIFs[j]), index, IP6_ADDR_PREFERRED);
445 netif_set_up(&(sNetIFs[j]));
446 netif_set_link_up(&(sNetIFs[j]));
449 netif_set_default(&(sNetIFs[0]));
454 while (!NetworkIsReady())
456 struct timeval lSleepTime;
457 lSleepTime.tv_sec = 0;
458 lSleepTime.tv_usec = 100000;
459 ServiceEvents(lSleepTime);
462 // FIXME: this is kinda nasty :(
463 // Force new IP address to be ready, bypassing duplicate detection.
465 for (size_t j = 0; j < gNetworkOptions.TapDeviceName.size(); j++)
467 if (j < gNetworkOptions.LocalIPv6Addr.size())
469 netif_ip6_addr_set_state(&(sNetIFs[j]), 2, 0x30);
473 netif_ip6_addr_set_state(&(sNetIFs[j]), 1, 0x30);
477 #if INET_CONFIG_ENABLE_DNS_RESOLVER
478 if (gNetworkOptions.DNSServerAddr != IPAddress::Any)
480 #if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5
481 ip_addr_t dnsServerAddr = gNetworkOptions.DNSServerAddr.ToLwIPAddr();
482 #else // LWIP_VERSION_MAJOR <= 1
483 #if INET_CONFIG_ENABLE_IPV4
484 ip_addr_t dnsServerAddr = gNetworkOptions.DNSServerAddr.ToIPv4();
485 #else // !INET_CONFIG_ENABLE_IPV4
486 #error "No support for DNS Resolver without IPv4!"
487 #endif // !INET_CONFIG_ENABLE_IPV4
488 #endif // LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5
490 dns_setserver(0, &dnsServerAddr);
492 #endif // INET_CONFIG_ENABLE_DNS_RESOLVER
496 #endif // !CHIP_SYSTEM_CONFIG_USE_SOCKETS
499 lContext = sLwIPEventQueue;
501 #endif // CHIP_SYSTEM_CONFIG_USE_LWIP
503 gInet.Init(gSystemLayer, lContext);
506 void ServiceEvents(struct ::timeval & aSleepTime)
508 static bool printed = false;
512 #if CHIP_SYSTEM_CONFIG_USE_LWIP && !CHIP_SYSTEM_CONFIG_USE_SOCKETS
513 if (NetworkIsReady())
516 printf("CHIP node ready to service events; PID: %d; PPID: %d\n", getpid(), getppid());
521 #if CHIP_SYSTEM_CONFIG_USE_SOCKETS
522 fd_set readFDs, writeFDs, exceptFDs;
529 #if CHIP_SYSTEM_CONFIG_USE_SOCKETS
530 if (gSystemLayer.State() == System::kLayerState_Initialized)
531 gSystemLayer.PrepareSelect(numFDs, &readFDs, &writeFDs, &exceptFDs, aSleepTime);
532 #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS
534 #if CHIP_SYSTEM_CONFIG_USE_SOCKETS
535 if (gInet.State == InetLayer::kState_Initialized)
536 gInet.PrepareSelect(numFDs, &readFDs, &writeFDs, &exceptFDs, aSleepTime);
537 #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS
539 int selectRes = select(numFDs, &readFDs, &writeFDs, &exceptFDs, &aSleepTime);
542 printf("select failed: %s\n", ErrorStr(System::MapErrorPOSIX(errno)));
545 #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS
547 if (gSystemLayer.State() == System::kLayerState_Initialized)
549 #if CHIP_SYSTEM_CONFIG_USE_LWIP
550 static uint32_t sRemainingSystemLayerEventDelay = 0;
551 #endif // CHIP_SYSTEM_CONFIG_USE_LWIP
553 #if CHIP_SYSTEM_CONFIG_USE_SOCKETS
555 gSystemLayer.HandleSelectResult(selectRes, &readFDs, &writeFDs, &exceptFDs);
557 #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS
559 #if CHIP_SYSTEM_CONFIG_USE_LWIP
560 if (gSystemLayer.State() == System::kLayerState_Initialized)
562 if (sRemainingSystemLayerEventDelay == 0)
564 gSystemLayer.DispatchEvents();
565 sRemainingSystemLayerEventDelay = gNetworkOptions.EventDelay;
568 sRemainingSystemLayerEventDelay--;
570 // TODO: Currently timers are delayed by aSleepTime above. A improved solution would have a mechanism to reduce
571 // aSleepTime according to the next timer.
573 gSystemLayer.HandlePlatformTimer();
575 #endif // CHIP_SYSTEM_CONFIG_USE_LWIP
578 #if CHIP_SYSTEM_CONFIG_USE_LWIP && !CHIP_SYSTEM_CONFIG_USE_SOCKETS
579 #if CHIP_TARGET_STYLE_UNIX
580 // TapAddrAutoconf and TapInterface are only needed for LwIP on
581 // sockets simulation in which a host tap/tun interface is used to
582 // proxy the LwIP stack onto a host native network interface.
583 // CollectTapAddresses() is only available on such targets.
585 TapInterface_Select(&(sTapIFs[0]), &(sNetIFs[0]), aSleepTime, gNetworkOptions.TapDeviceName.size());
586 #endif // CHIP_TARGET_STYLE_UNIX
587 #endif // CHIP_SYSTEM_CONFIG_USE_LWIP && !CHIP_SYSTEM_CONFIG_USE_SOCKETS
589 if (gInet.State == InetLayer::kState_Initialized)
591 #if CHIP_SYSTEM_CONFIG_USE_SOCKETS
593 gInet.HandleSelectResult(selectRes, &readFDs, &writeFDs, &exceptFDs);
595 #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS
599 #if CHIP_SYSTEM_CONFIG_USE_LWIP && !CHIP_SYSTEM_CONFIG_USE_SOCKETS
600 static bool NetworkIsReady()
604 for (size_t j = 0; j < gNetworkOptions.TapDeviceName.size(); j++)
606 for (int i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++)
608 if (!ip6_addr_isany(netif_ip6_addr(&(sNetIFs[j]), i)) && ip6_addr_istentative(netif_ip6_addr_state(&(sNetIFs[j]), i)))
618 static void OnLwIPInitComplete(void * arg)
620 printf("Waiting for addresses assignment...\n");
623 #endif // CHIP_SYSTEM_CONFIG_USE_LWIP && !CHIP_SYSTEM_CONFIG_USE_SOCKETS
625 void ShutdownNetwork()
628 #if CHIP_SYSTEM_CONFIG_USE_LWIP
633 void DumpMemory(const uint8_t * mem, uint32_t len, const char * prefix, uint32_t rowWidth)
635 int indexWidth = snprintf(nullptr, 0, "%X", len);
640 for (uint32_t i = 0; i < len; i += rowWidth)
642 printf("%s%0*X: ", prefix, indexWidth, i);
644 uint32_t rowEnd = i + rowWidth;
647 for (; j < rowEnd && j < len; j++)
648 printf("%02X ", mem[j]);
650 for (; j < rowEnd; j++)
653 for (j = i; j < rowEnd && j < len; j++)
654 if (isprint(static_cast<char>(mem[j])))
655 printf("%c", mem[j]);
663 void DumpMemory(const uint8_t * mem, uint32_t len, const char * prefix)
665 const uint32_t kRowWidth = 16;
667 DumpMemory(mem, len, prefix, kRowWidth);
670 static void RebootCallbackFn()
674 chip::Platform::ScopedMemoryBuffer<char *> lArgv;
675 if (!lArgv.Alloc(static_cast<size_t>(sRestartCallbackCtx.mArgc + 2)))
677 printf("** failed to allocate memory **\n");
681 if (gSigusr1Received)
683 printf("** skipping restart case after SIGUSR1 **\n");
687 for (i = 0; sRestartCallbackCtx.mArgv[i] != nullptr; i++)
689 if (strcmp(sRestartCallbackCtx.mArgv[i], "--faults") == 0)
691 // Skip the --faults argument for now
695 lArgv[j++] = sRestartCallbackCtx.mArgv[i];
700 for (size_t idx = 0; lArgv[idx] != nullptr; idx++)
702 printf("argv[%d]: %s\n", static_cast<int>(idx), lArgv[idx]);
705 // Need to close any open file descriptor above stdin/out/err.
706 // There is no portable way to get the max fd number.
707 // Given that CHIP's test apps don't open a large number of files,
708 // FD_SETSIZE should be a reasonable upper bound (see the documentation
710 for (int fd = 3; fd < FD_SETSIZE; fd++)
715 printf("********** Restarting *********\n");
717 execvp(lArgv[0], lArgv.Get());
723 static void PostInjectionCallbackFn(nl::FaultInjection::Manager * aManager, nl::FaultInjection::Identifier aId,
724 nl::FaultInjection::Record * aFaultRecord)
726 uint16_t numargs = aFaultRecord->mNumArguments;
729 printf("***** Injecting fault %s_%s, instance number: %u; reboot: %s", aManager->GetName(), aManager->GetFaultNames()[aId],
730 aFaultRecord->mNumTimesChecked, aFaultRecord->mReboot ? "yes" : "no");
733 printf(" with %u args:", numargs);
735 for (i = 0; i < numargs; i++)
737 printf(" %d", aFaultRecord->mArguments[i]);
744 static bool PrintFaultInjectionMaxArgCbFn(nl::FaultInjection::Manager & mgr, nl::FaultInjection::Identifier aId,
745 nl::FaultInjection::Record * aFaultRecord, void * aContext)
747 const char * faultName = mgr.GetFaultNames()[aId];
749 if (gFaultInjectionOptions.PrintFaultCounters && aFaultRecord->mNumArguments)
751 printf("FI_instance_params: %s_%s_s%u maxArg: %u;\n", mgr.GetName(), faultName, aFaultRecord->mNumTimesChecked,
752 aFaultRecord->mArguments[0]);
758 static bool PrintCHIPFaultInjectionMaxArgCbFn(nl::FaultInjection::Identifier aId, nl::FaultInjection::Record * aFaultRecord,
761 nl::FaultInjection::Manager & mgr = chip::FaultInjection::GetManager();
763 return PrintFaultInjectionMaxArgCbFn(mgr, aId, aFaultRecord, aContext);
766 static bool PrintSystemFaultInjectionMaxArgCbFn(nl::FaultInjection::Identifier aId, nl::FaultInjection::Record * aFaultRecord,
769 nl::FaultInjection::Manager & mgr = chip::System::FaultInjection::GetManager();
771 return PrintFaultInjectionMaxArgCbFn(mgr, aId, aFaultRecord, aContext);
774 void SetupFaultInjectionContext(int argc, char * argv[])
776 SetupFaultInjectionContext(argc, argv, nullptr, nullptr);
779 void SetupFaultInjectionContext(int argc, char * argv[], int32_t (*aNumEventsAvailable)(),
780 void (*aInjectAsyncEvents)(int32_t index))
782 nl::FaultInjection::Manager & weavemgr = chip::FaultInjection::GetManager();
783 nl::FaultInjection::Manager & systemmgr = chip::System::FaultInjection::GetManager();
785 sRestartCallbackCtx.mArgc = argc;
786 sRestartCallbackCtx.mArgv = argv;
788 nl::FaultInjection::SetGlobalContext(&sFaultInjectionGlobalContext);
790 memset(&sFuzzECHeaderCb, 0, sizeof(sFuzzECHeaderCb));
791 sFuzzECHeaderCb.mCallBackFn = PrintCHIPFaultInjectionMaxArgCbFn;
792 weavemgr.InsertCallbackAtFault(chip::FaultInjection::kFault_FuzzExchangeHeaderTx, &sFuzzECHeaderCb);
794 if (aNumEventsAvailable && aInjectAsyncEvents)
796 memset(&sAsyncEventCb, 0, sizeof(sAsyncEventCb));
797 sAsyncEventCb.mCallBackFn = PrintSystemFaultInjectionMaxArgCbFn;
798 systemmgr.InsertCallbackAtFault(chip::System::FaultInjection::kFault_AsyncEvent, &sAsyncEventCb);
800 chip::System::FaultInjection::SetAsyncEventCallbacks(aNumEventsAvailable, aInjectAsyncEvents);