95 Commits

Author SHA1 Message Date
Abtin Keshavarzian 86b8bf6de4 [nexus] add support for CLI testing (#13110)
This commit adds support for interacting with nodes via the CLI in the
Nexus simulation framework. This enables writing higher-level
integration tests that verify stack behavior and state through
standard CLI commands.

Key changes:
- Integrated `Cli::Interpreter` into the `Nexus::Node` class.
- Added `Node::InputCli()` to allow sending commands to a node with
  `printf`-style formatting.
- Implemented output capturing logic in `Node::HandleCliOutput()` to
  buffer and parse CLI responses into individual lines, stored in a
  `CliOutputArray`.
- Added helper methods to `CliOutputLine` for matching and validating
  the captured output.
- Added a new `cli_basic` Nexus test to demonstrate and validate the
  CLI interaction functionality.
2026-05-18 13:03:46 -07:00
Jonathan Hui 254043deec [nexus] add gRPC support and live demo (#12898)
This commit introduces gRPC support to the Nexus simulator, enabling
remote control and monitoring of simulations. This infrastructure allows
external tools and visualizers to interact with the simulated network
in real-time.

Key changes:
- Defined `simulation.proto` providing the `NexusService` definition for
  simulation control and event streaming.
- Implemented `GrpcServer` in `nexus_grpc.cpp` which functions as a
  Nexus simulation observer, pushing events to connected clients.
- Added RPCs for dynamic node creation, position updates, node state
  control, and network orchestration (forming and joining).
- Implemented a real-time event stream that includes node state changes,
  link updates, and packet captures (with basic protocol decoding).
- Introduced `nexus_native.cpp` as an entry point for a persistent
  simulation server that can be controlled via gRPC.
- Updated `Core` and `Observer` interfaces to support a list of
  concurrent observers instead of a single instance.
- Enhanced the CMake build system to optionally find and link against
  gRPC and Protobuf, including automatic source generation.
- Updated CI (GitHub Actions) to include build and test steps for the
  new gRPC functionality.
- Added comprehensive unit tests in `test_grpc.cpp` to verify all
  exposed gRPC service methods.
2026-04-16 22:05:19 -05:00
Jonathan Hui 47860a4eb4 [nexus] move multiple instance config to nexus config header (#12890)
This commit moves the `OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE`
configuration from the build scripts to the nexus-specific core
configuration header file.

Specifically:
- Added `#define OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE 1` to
  `tests/nexus/openthread-core-nexus-config.h`.
- Removed `-DOT_MULTIPLE_INSTANCE=ON` from `tests/nexus/build.sh`.
- Removed `-DOT_MULTIPLE_INSTANCE=ON` from `tests/fuzz/oss-fuzz-build`.

This change centralizes nexus-specific configurations in the header
file, making the build scripts cleaner and ensuring consistent
configuration across different build environments that use the
nexus core config."
2026-04-14 13:12:29 -05:00
Abtin Keshavarzian cb4b28313b [logging] add support for per-instance log levels (#12740)
This commit introduces the ability to set and manage log levels on a
per-instance basis when dynamic logging is enabled, while maintaining
backward compatibility with existing logging behaviors.

The existing `otLoggingGetLevel()` and `otLoggingSetLevel()` APIs are
repurposed to manage the "global" log level. They continue to behave
exactly as before in both single-instance and multi-instance
configurations, ensuring that existing users of these APIs do not need
to change their implementations. To provide more granular control, new
APIs `otGetLogLevel()` and `otSetLogLevel()` are added to handle
per-instance log levels.

Specifically, this commit makes the following changes:
- Adds `mLogLevel` to `Instance` to track the instance-specific log
  level.
- Renames the global log level static variable to `sGlobalLogLevel` and
  introduces `GetGlobalLogLevel()` and `SetGlobalLogLevel()` to manage
  it in a multi-instance configuration.
- Updates `otGetLogLevel()` and `otSetLogLevel()` APIs to handle
  per-instance log level retrieval and configuration. If a specific
  level is not set for an instance, it falls back to the global
  log level.
- Adds `mIsLogLevelSet` to distinguish between an explicitly set
  instance log level and the global fallback in multi-instance builds.
- Introduces `otPlatLogHandleLogLevelChanged()` platform callback to
  notify the platform when an instance-specific log level is updated.
- Updates Nexus tests to use `SetGlobalLogLevel()` instead of the
  deprecated instance `SetLogLevel()` method.
2026-03-27 00:24:49 -05:00
Jonathan Hui 202d5df96d [nexus] implement CSL transmitter and receiver (#12595)
This commit implements CSL transmitter and receiver functionality in
the Nexus simulation platform. It enables the necessary OpenThread
configurations and provides the platform-level support for CSL.

It also implements the otPlatRadioGetNow platform API to provide a
high-resolution 64-bit microsecond time base, which is required for
accurate CSL timing and synchronization.

Changes:
- Added GetNowMicro64() to Nexus::Core to expose the raw 64-bit
  microsecond timer.
- Implemented otPlatRadioGetNow() in nexus_radio.cpp.
- Enabled OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE and
  OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE in Nexus config.
- Added otRadioContext to Nexus::Radio to track CSL parameters and
  manage security material for radio operations.
- Implemented otPlatRadioEnableCsl, otPlatRadioResetCsl,
  otPlatRadioUpdateCslSampleTime, and otPlatRadioGetCslAccuracy.
- Implemented otPlatRadioSetMacKey, otPlatRadioSetMacFrameCounter,
  and otPlatRadioSetAlternateShortAddress to keep radio context
  synchronized with OpenThread stack.
- Updated otPlatRadioSetExtendedAddress and otPlatRadioEnableCsl to
  use AsCoreType for better readability and project conventions.
- Moved Radio member initializations to the initializer list in its
  constructor.
- Refactored radio SFD processing: moved otMacFrameProcessTxSfd and
  UpdateFcs from otPlatRadioTransmit (radio platform) to
  Core::ProcessRadio (simulation engine), ensuring CSL IEs and
  security headers are updated exactly when transmission starts.
- Enhanced Nexus::Core::ProcessRadio to support generating Enhanced
  ACKs with CSL IEs for 802.15.4-2015 frames.
- Updated Nexus and fuzz build systems to include necessary Nexus
  platform and utils headers/utilities.
2026-03-03 15:32:05 -06:00
Jonathan Hui 62ad025d88 [fuzz] update build script to checkout submodules (#12216) 2025-12-17 07:56:54 -08:00
Abtin Keshavarzian 61e43cffb9 [fuzz] fix warning when building fuzzer source files (#12130)
Add `SuccessOrQuit()` to check the return `Error` value of
`RoutingManager::SetEnabled()` in `fuzz_*.cpp` source files. This
addresses warnings about ignoring the return value.
2025-11-12 20:37:17 +01:00
Abtin Keshavarzian 6cc2a57742 [fuzz] rename fuzzer source files and update cmake macro (#12125)
Rename all fuzzer source files in `tests/fuzz` from `{name}.cpp` to
`fuzz_{name}.cpp`.

Update the `ot_nexus_test` macro in `tests/fuzz/CMakeLists.txt` to
reflect this change, using `fuzz_{name}.cpp` as the source file while
naming the test `{name}-fuzzer`.

This change improves consistency and makes it easier to distinguish
fuzzer source files from other similarly named files during searches.
2025-11-08 11:02:48 -08:00
Abtin Keshavarzian b492922a9c [border-router] centralize infra-if management in InfraIf (#12046)
This change moves the management of the infrastructure interface state
out of the `RoutingManager` and centralizes it within the `InfraIf`
class. This makes `InfraIf` a more self-contained component and
simplifies the logic in `RoutingManager`.

The `RoutingManager` now depends on an initialized `InfraIf`. Its
`Init()` method is simplified and is now called from
`InfraIf::Init()`.

The public API `otBorderRoutingInit()` now directly initializes the
`InfraIf`. The `InfraIf::Init()` method is updated to support
re-initialization, allowing to switch to a new interface. When
switching, it ensures that components on the previous interface are
stopped before restarting on the new one.
2025-10-24 06:55:11 +08:00
Abtin Keshavarzian 2596c9486b [fuzz] increase wait time in CLI fuzzer (#11999)
Increases the `nexus.AdvanceTime()` in the CLI fuzzer test from 10 to
60 seconds to make the test more robust.

For example, the previous 10-second wait was not sufficient for
`Dns::Client` operations to complete, especially considering retries.
This could cause false fuzzer memory leak reports.
2025-10-06 20:26:03 -07:00
Jonathan Hui 3e9c7285c8 [fuzz] fix bounds checking in cli-fuzzer (#11991) 2025-10-02 15:59:05 -07:00
Jonathan Hui 2b85b0160f [fuzz] add CLI test (#11946) 2025-09-16 16:34:50 -07:00
Jonathan Hui 2bc7712f57 [fuzz] add fuzzer for otPlatTrelHandleReceived (#11779) 2025-08-08 22:54:35 -07:00
Jonathan Hui 956e1a0c7d [fuzz] add fuzzer for otIp6Send (#11790) 2025-08-05 19:55:50 -07:00
Jonathan Hui 31adbd0edc [fuzz] add fuzzer for otPlatInfraIfRecvIcmp6Nd (#11773) 2025-08-02 10:23:58 -07:00
Jonathan Hui 9cd5a2d93e [fuzz] add fuzzer for otPlatMdnsHandleReceive (#11772) 2025-07-31 13:28:23 -07:00
Jonathan Hui 206698702d [fuzz] load only value enum values (#11573) 2025-06-04 13:25:32 -07:00
Jonathan Hui 45fc50cb2e [fuzz] allow border router services to start (#11561) 2025-06-04 11:19:35 -07:00
Jonathan Hui f9be8f76ee [fuzz] enable border router services (#11557)
- Border Routing Manager
- DHCPv6 PD
- NAT64
- SRP Server
- TCP
2025-06-02 15:58:25 -07:00
Jonathan Hui cbe3654ce7 [fuzz] avoid undefined enum values (#11549) 2025-05-30 11:18:22 -07:00
Jonathan Hui 6d40977782 [fuzz] migrate fuzz framework to nexus platform (#11538) 2025-05-28 18:32:04 -07:00
Yakun Xu 025d84ba1e [fuzz] expect no ACK if TX frame is invalid (#10951)
The Sequence Number Suppression field and AR can be both 1 in fuzz test,
in which case, the frame is not valid. And no ack should be expected.
This commit changes the expectation in this case.
2024-11-21 18:13:27 -08:00
Yakun Xu e219fe92f1 [mac] support frames without sequence number (#10544)
This commit adds the capability to support frames without sequence
number.
2024-08-02 09:50:45 -07:00
Zhanglong Xia 215c23f2a6 [diag] add diag output callback (#10354)
The length of diag output messages is limited by the diag buffer size.
Developers have to change the diag buffer size to allow diag module to
output long messages. If diag output messages become longer and
longer, developers have to keep changing the diag buffer size.

This commit adds an output callback to diag module to output diag
messages.  Then the length of diag output messages won't be limited by
the diag buffer size.
2024-06-19 20:27:35 -07:00
Łukasz Duda 59b87d6d48 [fuzz] fix typo and enable SRP Advertising Proxy (#10300)
This commit fixes the typo and enables SRP_ADV_PROXY - also by turning
on the dependent components.

Signed-off-by: Łukasz Duda <lukasz.duda@nordicsemi.no>
2024-05-28 09:18:17 -07:00
Jonathan Hui ee1ae6c96c [tests] do not build unit tests in oss-fuzz (#10259) 2024-05-17 08:47:06 -07:00
Abtin Keshavarzian b212a0a748 [srp] implement AdvertisingProxy and define Dnssd platform APIs (#9268)
This commit adds a generic SRP Advertising Proxy implementation to
OpenThread core, which uses a set of newly defined `otPlatDnssd`
platform APIs for DNS-SD (mDNS) support on infrastructure network on
a Border Router.

`Srp::Server` provides `ServiceUpdateHandler` callback mechanism that
allows platforms to implement their own advertising proxy function.
While this is still supported, the new generic advertising proxy
implementation makes it easier to port and support the proxy function
on new platforms. The platform needs to provide the DNS-SD platform
APIs, which are designed to be simple and easy to implement.

The `AdvertisingProxy` directly interacts with `Srp::Server` and its
registered `Host` and `Service` entries, tracking whether an entry
has been successfully advertised, is currently being advertised, or
has been replaced by a new registration.

The `AdvertisingProxy` ensures that consecutive SRP updates for the
same host or service are committed on the server in the order they
are received, even if their advertisements are finished in a
different order. This is important for SRP Replication support, as
the server may receive a large number of SRP updates back-to-back for
the same host.

The `AdvertisingProxy` will also register key records for SRP host and
service instance names. This will keep the claim on the name of a
removed entry while its key lease is not expired. It is also used
when an SRP host registration has no off-mesh routable address.

This commit adds a detailed unit test `test_srp_adv_proxy` that
validates the `AdvertisingProxy` under many scenarios. The test
covers a range of cases, including delayed registration callbacks and
timeouts, new registrations replacing outstanding advertisements,
platform DNS-SD state changes and failures, host address changes
adding/removing OMR addresses.
2024-02-09 10:43:47 -08:00
Jonathan Hui 1e82c4e962 [cmake] always define OPENTHREAD_FTD/MTD/RADIO (#9733) 2023-12-20 14:44:41 -08:00
Marek Porwisz 834c8cbc8e [spinel] add support for multiple spinel interfaces (#9360)
This feature allows the RCP to support multiple host stacks on different PANs
by making use of the spinel Interface ID.

Created unit tests for testing multipan feature with multiple ot-instance
support.

Based on Si-Labs PR #8914 by @parag-silabs, but a little different approach.
Instead of handling everything by a single sub-mac instance, multiple
OpenThread instances are created on RCP side that map to different IID.
Thanks to this there are separate data kept for each interface. Platform
is able to determine interface by ot instance pointer passed as an argument
to most of the API functions.
Tx/scan queue was removed as it is possible to request transmission in
parallel, it is up to the platform to decide if it should fail or queue
second tx or it has two radios available.

NOTE:
Platform needs to provide different otRadioFrame of each instance and
the processing needs to take into account the instance being used.

Signed-off-by: Marek Porwisz <marek.porwisz@nordicsemi.no>
2023-11-28 16:16:37 -08:00
Eduardo Montoya 193e77e40e [radio] add OT_RADIO_CAPS_RX_ON_WHEN_IDLE capability (#9554) (#9554)
Add a new `OT_RADIO_CAPS_RX_ON_WHEN_IDLE` radio capability which lets
OpenThread know what the radio idle state operation will be: receive
or sleep.

This allows to save power on sleepy devices since the active --> idle
transition is much faster, specially for the cases in which there is
some kind of serialization between OpenThread core and the radio
driver.
2023-11-14 11:46:10 +01:00
Yakun Xu 11a38a63de [build] remove autotools (#9027)
This commit removes autotools support from OpenThread project.
2023-06-28 08:54:23 -07:00
Abtin Keshavarzian 0f94f26a20 [net-diag] introduce Server and Client classes (#8936)
This commit introduces `Server` and `Client` classes breaking the
`NetworkDiagnostic` module into two components. The `Server` responds
to queries and requests (handling Net Diag TMF commands), while
`Client` issues queries/requests and processes responses. The
`Server` is available under both FTD and MTD (which follows the
requirement of Thread spec). The client is enabled using newly added
`OPENTHREAD_CONFIG_TMF_NETDIAG_CLIENT_ENABLE` config option which is
also available as `OT_NETDIAG_CLIENT` CMake option or the autoconf
build switch `NETDIAG_CLIENT`. The client functionality is by default
enabled on Border Routers (tied to `CONFIG_BORDER_ROUTING_ENABLE`
config).

The previous `TMF_NETWORK_DIAG_MTD_ENABLE` config is now removed
along with its CMake `OT_MTD_NETDIAG` and autoconf switch. This
commit adds checks to trigger build error if the previous config
and/or its related CMake option are used.
2023-04-07 15:58:07 -07:00
Li Cao 130ef49cc4 [thread-cert] add Low Power test case 7_1_02 (#8807) 2023-03-07 12:54:45 -08:00
Abtin Keshavarzian 091f68ed70 [child-supervision] mechanism to inform interval from child to parent (#7993)
This commit contains changes to child supervision feature. It adds a
new mechanism for a child to inform its desired supervision interval
to its parent. A new optional MLE TLV is added with type 27 and value
of `uint16_t` indicating the supervision interval in seconds. This
TLV is included in MLE Child ID Request and MLE Child Update Request
(sent from the child). The parent echoes back this TLV in the
corresponding responses to indicate that it supports supervision. This
commit changes the parent implementation to track the supervision
interval per child.

This commit also updates the OT public APIs along with the related
CLI commands:
- API now allows the supervision interval to be set on a child.
- New field in `otChildInfo` to indicate the child's supervision
  interval.
- New counter is added to track the number of supervision check
  timeouts failures on a child (intended for testing and debugging).

This commit adds a test `test_child_supervision` to cover behavior of
child supervision and its new behaviors.

This change allows backward compatibility: If the parent does not
support child supervision, it ignores the new TLV in the MLE messages
and the child would fall back to periodically exchanging MLE Child
Update Request with parent. If the child does not support supervision
and/or does not indicate its desired child supervision interval, the
parent will fall back to use the configured default interval.
2023-02-28 23:01:43 -08:00
Abtin Keshavarzian 99a615bec2 [clang-format] use AllowShortFunctionsOnASingleLine: All (#8502)
This commit updates `AllowShortFunctionsOnASingleLine` to `All`
from `InlineOnly`.
2022-12-08 09:34:05 -08:00
Jonathan Hui 9c467a23ae [clang-format] apply v14 changes (#8490) 2022-12-07 16:23:20 -08:00
Zhanglong Xia 11a24d111f [diag] add gpio diag command support (#8316) 2022-10-31 17:05:20 -07:00
Jonathan Hui 10de4c4f13 [fuzz] advance time before fuzz input enable to more services (#8243) 2022-10-06 08:54:00 -07:00
Jonathan Hui b3620ae51a [fuzz] add set -euxo pipefail to build script (#8222) 2022-09-30 11:24:20 -07:00
Jonathan Hui f6df50cde6 [fuzz] declare otPlatLog as weak (#8220) 2022-09-29 20:59:32 -07:00
Jonathan Hui e9877198c4 [fuzz] enable SRP server in fuzz targets (#8145) 2022-09-12 21:23:31 -07:00
Jonathan Hui 945edf1eb6 [fuzz] bump Thread version to 1.3 (#8145) 2022-09-12 21:23:31 -07:00
jinran-google c9f23ccdda [settings] set sensitive keys in platform settings initialization (#7496)
This commit makes the core pass the sensitive keys to the platform
settings initialization, so that the platform settings implementation
can know which keys are sensitive keys during the initializing and do
the migration when needed.
2022-03-24 21:22:32 -07:00
Abtin Keshavarzian ca3830fac2 [uptime] new feature to track OT instance uptime (in msec) (#6968)
This commit adds a new module `Uptime` which tracks the number of
milliseconds since OpenThread stack initialization as an `uint64_t`
value. It also adds public OT APIs to get the current uptime value
(either as the number of milliseconds or in human-readable string
format like "2 days 12:45:12.762"). A CLI `uptime` command is also
added. This feature can be enabled using the newly added config
option `OPENTHREAD_CONFIG_UPTIME_ENABLE` (or the related CMake
`OT_UPTIME` option).
2021-09-02 13:44:40 -07:00
Abtin Keshavarzian 2798cc9c05 [utils] adding HistoryTracker module (#6807)
This commit adds History Tracker feature and its CLI support. This
feature records history of different events as the Thread network
operates (e.g., history of RX and TX IPv6 messages or network info
changes).

Recorded entries are timestamped. When the history list is read, the
timestamps are given as the entry age relative to the time the list
is being read. For example in CLI a timestamp can be shown as
`02:31:50.628 ago` indicating the entry was recorded 2 hours, 31 min,
50 sec, and 628 msec ago. Number of days is added for events that are
older than 24 hours, e.g., `31 days 03:00:23.931 ago`. Timestamps use
millisecond accuracy and are tacked up to 49 days. If an event is
older than 49 days, the entry is still tracked in the list but the
timestamp is shown as old or `more than 49 days ago`.

The `HistoryTracker` currently maintains 3 lists. The Network Info
history tracks changes to Device Role, Mode, RLOC16 and Partition ID.
The RX/TX history list records information about the received/sent
IPv6 messages:
- Message type (UDP, TCP, ICMP6 (and its subtype), etc.)
- Source and destination IPv6 addresses and port numbers
- IPv6 payload length
- The message checksum (for UDP, TCP, or ICMP6).
- Whether or not the link-layer security was used
- Message priority: low, norm, high, net (for control messages)
- Short address (RLOC16) of neighbor who send/received the msg
- Received Signal Strength (in dBm) for RX only
- Radio link info (15.4/TREL) on which msg was sent/received
  (useful when `OPENTHREAD_CONFIG_MULTI_RADIO` is enabled)

Config `HISTORY_TRACKER_EXCLUDE_THREAD_CONTROL_MESSAGES` can be used
to configure `HistoryTracker` to exclude Thread Control message
(e.g., MLE, TMF) from TX and RX history.

The number of entries recorded for each history list is configurable
through a set of OpenThread config options, e.g., number of entries
in Network Info history list is specified by OpenThread config option
`OPENTHREAD_CONFIG_HISTORY_TRACKER_NET_INFO_LIST_SIZE`. The
`HistoryTracker` will keep the most recent entries overwriting oldest
ones when the list gets full.

This commit also adds support for `HistoryTracker` in CLI. The CLI
commands provide two style for printing the history information: A
table format (more human-readable) and list style (better suited for
parsing by machine/code). `README_HISTORY.md` is added to document
the commands and the info provided by each history list entry.

This commit also adds `test_history_tracker.py` test-case which
covers the behavior of `HistoryTracker`.
2021-08-12 15:47:26 -07:00
Abtin Keshavarzian 2e625bfe39 [netdata] adding NetworkData::Publisher (#6768)
This commit implements a new feature "Network Data Publisher" which
provides mechanisms to limit the number of similar entries (service
and/or prefix) in the Thread Network Data by monitoring the Network
Data and managing if or when to add or remove entries. This feature is
enabled using `OPENTHREAD_CONFIG_NETDATA_PUBLISHER_ENABLE` config, or
`NETDATA_PUBLISHER` in autoconf, or `OT_NETDATA_PUBLISHER` cmake
option.

This commit adds support for publishing DNS/SRP anycast/unicast
service, on-mesh prefix, and external route prefix entries.

When there is a request to publish an entry, the `Publisher` monitors
the Network Data and counts the number of similar entries. If there
are fewer entries than a desired target number, the entry is added
after a short random delay.

If there are too many similar entries, `Publisher` starts the process
of removing its own entry (again after some random wait time). When
removing entries, certain entries are preferred over others (e.g., an
entry from a router over one from an end-device or if they are from
the same type of node, the one with smaller RLOC16). If `Publisher`
determines that its own entry is a preferred one, it adds an extra
wait time before removing its entry. This gives higher chance for a
non-preferred entry from another device to be removed before removing
a preferred entry which helps towards quicker convergence of the
process to the desired number of entries.

On-mesh prefix and external route entries have a "preference" field.
When publishing such an entry, a matching entry in the network data is
counted only if its preference is same or higher than the entry's
preference. This ensures that a device with a higher preference entry
publishes its entry even when there are many lower preference similar
entries in the network data (potentially causing a lower preference
entry to be removed).

This commit also adds `test_netdata_publisher.py` to verify the
behavior of the `Publisher`.
2021-08-10 22:32:33 -07:00
Sam Kumar 6fa60be75c [tcp] add third_party module for TCPlp (#6885)
This commit creates a module in third_party for TCPlp code. It is a
placeholder for now; the actual code will be added in future commits.
2021-08-06 22:04:31 -07:00
Yakun Xu 6d447f96da [test] add 'ot-' prefix to test targets (#6550) 2021-05-04 15:41:51 -07:00
Abtin Keshavarzian 06ca5d855c [utils] add 'Utils::PingSender' (#6284)
This commit adds a new module `Utils::PingSender`. This module
is then used by CLI to support ping command.
2021-03-19 16:04:55 -07:00
Yakun Xu db1b980e57 [api] remove UART from in cli/ncp API (#6243)
This commit removes application library CLI/NCP dependency on platform
layer UART APIs. Instead, application layer provides callbacks sending
CLI/NCP data.

With this change, platforms with native support for formatted output
can simply implement the CLI output callback with something like
`vprintf()`.
2021-03-18 22:13:05 -07:00