Commit Graph

1266 Commits (314ff9890393c03e616b4aa78bd1ae6f0acc0e0a)

Author SHA1 Message Date
Vladimir Oltean 314ff98903 ts2phc: instantiate a pmc node
This introduces the '-a' option in ts2phc, an option inspired from
phc2sys that puts the clocks in "automatic" mode. In this mode, ts2phc
listens, as a PMC, to port state change events from ptp4l, and detects
which port state machine, if any, has transitioned to PS_SLAVE. That
port's clock will become the synchronization master for the hierarchy
described by ts2phc.

The use case is a multi-switch DSA setup with boundary_clock_jbod, where
there is only one grandmaster, connected to one switch's port. The other
switches, connected together through a PPS signal, must adapt themselves
to this new source of time, while the switch connected to the GM must
not be synchronized by ts2phc because it is already synchronized by
ptp4l.

Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
2020-08-30 02:56:48 +03:00
Vladimir Oltean 3f2e73e91b ts2phc: instantiate a full clock structure for every PHC master
This propagates the use of "struct ts2phc_private" all the way into the
master API, in preparation of a new use case that will be supported
soon: some PPS masters (to be precise, the "PHC" kind) instantiate a
struct clock which could be disciplined by ts2phc.

When a PHC A emits a pulse and another PHC B timestamps it, the offset
between their precise timestamps can be used to synchronize either one
of them. So far in ts2phc, only the slave PHC (the one using extts) has
been synchronized to the master (the one using perout).

This is partly because there is no proper kernel API to report the
precise timestamp of a perout pulse. We only have the periodic API, and
that doesn't report precise timestamps either; we just use vague
approximations of what the PPS master PHC's time was, based on reading
that PHC immediately after a slave extts event was received by the
application. While this is far from ideal, it does work, and does allow
PHC A to be synchronized to B.

This is particularly useful with the yet-to-be-introduced "automatic"
mode of ts2phc (similar to '-a' of phc2sys), and the PPS distribution
tree is fixed in hardware (as opposed to port states, which in
"automatic" mode are dynamic, as the name suggests).

Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
2020-08-30 02:56:13 +03:00
Vladimir Oltean 1967a5fc26 ts2phc: instantiate a full clock structure for every slave PHC
Slaves in ts2phc are PHC devices that implement the extts kernel API.
They are slaves just in the sense that they timestamp a pulse emitted by
somebody else.

Currently in ts2phc, PPS slaves are also the only candidates for the
clocks that get synchronized. There are 2 aspects that make this too
restrictive:

- Not all PPS slaves may be synchronization slaves. Consider a dynamic
  environment of multiple DSA switches using boundary_clock_jbod, and
  only one port is in the PS_SLAVE state. In that case, the clock of
  that port should be the synchronization master (called the "source
  clock" from now on, as far as ts2phc is concerned), regardless of
  whether it supports the extts API or not.

- Not all synchronization slaves may be PPS slaves. Specifically, the
  "PHC" type of PPS master in ts2phc can also be, fundamentally,
  disciplined. The code should be prepared to handle this by recognizing
  that things that can be disciplined by a servo should be represented
  by a "struct clock", and things that can timestamp external events
  should be represented by a "struct ts2phc_slave".

Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
2020-08-30 02:56:10 +03:00
Vladimir Oltean 703c3c7bc7 ts2phc: create a private data structure
Eliminate the ad-hoc use of global variables in the ts2phc program by
introducing one data structure that incorporates them. This might make
the code more understandable to people coming from a kernel background,
since it resembles the type of data organization used there. It is also
now closer to the data organization of phc2sys, a similar program in
both purpose and implementation.

The reason why this is needed has to do with the ts2phc polymorphism for
a PPS master.

In the next patches, PPS masters will expose a struct clock, which will
be synchronized from the main ts2phc.c.

Not all PPS masters will expose a clock, only the PHC kind will. So the
current object encapsulation model needs to be loosened up little bit,
because the main ts2phc.c needs to synchronize a list of clocks, list
which is populated by the slaves and the masters which are capable of
being synchronized.

So instead of having the translation modules of ts2phc communicate
through global variables, let's make struct ts2phc_private the common
working space for the entire program, which is a paradigm that is more
natural.

Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
2020-08-30 02:28:04 +03:00
Vladimir Oltean f44b3d8b6c phc2sys: break out pmc code into pmc_common.c
The code through which phc2sys sends various PTP management messages to
ptp4l via pmc can be reused.

This patch is a trivial movement of that code to a separate translation
module, outside of phc2sys. This makes it available to other programs
that want to subscribe to port state change events too, such as ts2phc.

Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
2020-08-30 01:48:48 +03:00
Vladimir Oltean cc88812d12 phc2sys: make PMC functions non-static
In preparation of a trivial movement of code to pmc_common.c, remove the
"static" keyword from the functions that will end up there, since they
will be still called from phc2sys.c for now.

Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
2020-08-30 01:48:04 +03:00
Vladimir Oltean 317e419d1f phc2sys: extract PMC functionality into a smaller struct pmc_node
This creates a smaller structure within phc2sys_private, which embeds
all properties related to the PMC. This structure is called "pmc_node",
which is somewhat reminiscent of the old name of phc2sys_private (struct
node). But the advantage is that struct pmc_node can be reused by other
modules.

The phc2sys code that is executed upon a subscription update,
recv_subscribed, is now refactored into a function pointer callback. It
is imaginable that other programs might to do other things in it.
Note that putting this function pointer in struct pmc_node is, long
term, maybe not the best of choices. It is only needed from the
run_pmc_events() code path, and could be therefore passed as a more
local callback to that function only. However, for that, further
refactoring is needed inside the common run_pmc() function, so that is
being left for another time.

Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
2020-08-30 01:44:33 +03:00
Vladimir Oltean 2f8470980d phc2sys: break long lines in the PTP management message accessors
In preparation of moving these functions to pmc_common.c, break the
lines to a maximum of 80 characters, otherwise checkpatch will complain.

Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
2020-08-30 00:34:01 +03:00
Vladimir Oltean 8001bd3c4e port: switch PHC in jbod mode when in UNCALIBRATED or SLAVE state
In the (still downstream) patch "Add BMCA support for IEEE
802.1AS-2011", we are making ieee8021as_fsm() skip the UNCALIBRATED
state. This means that the PHC on which the servo loop is applied will
never be switched in JBOD mode. Make the switching logic take place
either on a MASTER to SLAVE, or on a MASTER to UNCALIBRATED transition.

Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
2020-08-30 00:26:30 +03:00
Rodney Greenstreet 76657d6da3 clock: redecide state if get EV_FAULT_DETECTED event
IEEE 802.1AS-2011's methodology for faults is to avoid waiting
in that FAULTY state in hopes that management will notice.
Instead, move on to search for a valid non-faulty state. If
supported, the fault is logged so that management can notice
later, but that logging isn't a requirement.

This patch is to invoke BMCA to redecide state if get
EV_FAULT_DETECTED event.

Signed-off-by: Rodney Greenstreet <rodney.greenstreet@ni.com>
Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
2020-08-30 00:26:30 +03:00
Rodney Greenstreet 416058d136 port: drop erroneous neighbor rate ratio
When a connected peer introduces a time discontinuities in between
consecutive peer-delay measurements (i.e. a jump in time in
consecutive PDelay response), an erroneous neighbor rate ratio is
calculated. This change disqualifies any neighbor rate ratio that
exceeds +/- 100 ppm, as required by IEEE 802.1AS-2011 Anex B.1.1.

This patch is to check and drop erroneous neighbor rate ratio to
ensure IEEE 802.1AS-2011 Anex B.1.1.

Signed-off-by: Rodney Greenstreet <rodney.greenstreet@ni.com>
Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
2020-08-30 00:26:30 +03:00
Yangbo Lu f8ffb2cf5a Add BMCA support for IEEE 802.1AS-2011
According to IEEE 802.1AS-2011, the BMCA used in gPTP is the same
as that used in IEEE 1588 with the following exceptions:

(1) Announce messages received on a slave port that were not sent
by the receiving time-aware system are used immediately,
i.e., there is no foreign-master qualification.

(2) A port that the BMCA determines should be a master port enters
the master state immediately, i.e., there is no pre-master state.

(3) The uncalibrated state is not needed and, therefore, not used.

(4) All time-aware systems are required to participate in best master
selection (even if it is not grandmaster capable).

This patch is to support (1) by using a specific FOREIGN_MASTER_THRESHOLD
case. (Treat FOREIGN_MASTER_THRESHOLD as 1.)
To support (2) and (3), reuse ptp_fsm and drop pre-master/uncalibrated
states. The (4) item is supported since IEEE 802.1AS reuses OC/BC.

Signed-off-by: Erik Hons <erik.hons@ni.com>
Signed-off-by: Rodney Greenstreet <rodney.greenstreet@ni.com>
Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
2020-08-30 00:26:30 +03:00
Yangbo Lu 1486660e95 Add IEEE 802.1AS-2011 time-aware bridge support
This patch is to add IEEE 802.1AS-2011 time-aware bridge support
based on current BC clock type. It implements only time information
relay, and BMCA was not touched. To run it, the profile gPTP.cfg could
be used with multiple interfaces specified using -i option.

The main code changes are,
- Create syfu_relay_info structure for time information relay.
- Implement port_syfu_relay_info_insert() to update follow_up (with TLV)
  message with time information for relay.

Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
2020-08-30 00:26:30 +03:00
Vladimir Oltean 14e09fd9ed phc2sys: rename struct node to struct phc2sys_private
We will be reusing some PMC code between phc2sys and ts2phc. In
preparation of that, we would like to extract the PMC related properties
of the current private program data structure of phc2sys, "struct node",
into something smaller that can be shared properly.

The "struct node" name is nice enough, so use that to denote the smaller
data structure for PMC from now on. Rename the bigger data structure to
phc2sys_private.

Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
2020-08-29 10:59:08 -07:00
Vladimir Oltean 380d023abb posix_clock_open: derive PHC index from device name if possible
Currently the PHC index is retrieved only through an ethtool ioctl if
the PHC is specified as an Ethernet interface. If it's a char device
such as /dev/ptp5, the phc_index will remain unpopulated. Try to infer
it from the char device's path.

This is useful when trying to determine whether multiple clocks are in
fact the same (such as /dev/ptp3 and sw1p3), just compare their PHC
index.

Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
2020-08-29 10:59:08 -07:00
Vladimir Oltean cef87c6f03 tmv: introduce an initializer from nanoseconds
Interestingly, although tmv_t is a wrapper over nanoseconds, there is no
initializer from a raw nanosecond value. So add one.

Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
2020-08-29 10:59:08 -07:00
Vladimir Oltean 6325880094 tmv: introduce a conversion helper from ptp_clock_time
This is useful when dealing with timestamps returned by various
ancillary PHC ioctl kernel APIs, such as extts.

Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
2020-08-29 10:59:08 -07:00
Jacob Keller 226c285ec4 phc_ctl: display all capability information
The capability command for phc_ctl does not display the number of pins
or the cross timestamping support. Add this as output so that the user
can see the complete device capabilities.

Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
2020-08-05 18:48:33 -07:00
Richard Cochran 3da961bb11 Version 3.0
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
2020-07-22 16:14:39 -07:00
Richard Cochran 1335db3bde ts2phc: Ignore pulses with invalid time stamps.
The API to obtain the time stamp of a PPS source indicates the validity of
the returned value.  However, the current code does not ever test the
validity information in any way.  This patch lets the clients ignore PPS
values that lack a valid time stamp.

Signed-off-by: Richard Cochran <richardcochran@gmail.com>
2020-07-22 14:56:36 -07:00
Richard Cochran 70c32043a5 ts2phc: Fix memory leak.
Each slave creates an instance of a servo.  However, when cleaning up, the
code neglected to free the servo, resulting in a memory leak.  This patch
fixes the issue by calling the appropriate method to destroy the servo.

Signed-off-by: Richard Cochran <richardcochran@gmail.com>
2020-07-22 14:52:48 -07:00
Richard Cochran 278d9f45ab ts2phc: Use proper close method on the error path.
When creating a ts2phc slave, a clock is obtained by invoking the
posix_clock_open() method.  However, in case of an error, the same clock
is closed again by calling close(2) on the associated file descriptor
directly.  While not incorrect, still the code should instead use the
close function that matches the open method.

Signed-off-by: Richard Cochran <richardcochran@gmail.com>
2020-07-22 14:49:05 -07:00
Vladimir Oltean 61c6a70898 phc2sys: provide missing kernel headers for sysoff functionality
Currently it is very finicky to deploy linuxptp in an automated build
system and make KBUILD_OUTPUT pick up the output of "make
headers_install" in order for the application to make full use of the
features exposed by the runtime kernel. And the toolchain/libc will
almost certainly never contain recent enough kernel headers to be of any
use here. And there's no good reason for that: the application can probe
at runtime for the sysoff methods supported by the kernel anyway.

So let's provide the kernel definitions for sysoff, sysoff_precise and
sysoff_extended, such that SYSOFF_COMPILE_TIME_MISSING is not something
that will bother us any longer.

Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
2020-06-24 16:09:47 -07:00
Richard Cochran cb3fbc1010 Catch unexpected socket polling errors.
The poll(2) system call may set POLLERR in the returned events.  Normally
no errors are returned unless specifically requested by setting an
appropriate socket option.  Nevertheless, the poll(2) API is quite generic,
and there is no guarantee that the kernel networking stack might push an
error event one day.  This patch adds defensive code in order to catch any
unexpected error condition.

Signed-off-by: Richard Cochran <richardcochran@gmail.com>
2020-06-24 11:02:02 -07:00
Georg Sauthoff b6fa222201 Eliminate isort
This saves a few bytes of static storage and less instructions are
executed when looking for the best offset.

Signed-off-by: Georg Sauthoff <mail@gms.tf>
2020-06-24 10:09:13 -07:00
Vladimir Oltean bf0a644b99 port: print sync/follow-up mismatch events
ptp4l is too silent when receiving, for whatever reason, out of order
messages. If the reordering is persistent (which is either a broken
network, or a broken kernel), the behavior looks like a complete
synchronization stall, since the application is designed to never
attempt to recover from such a condition.

At least save some people some debugging hours and print when the
application reaches this code path. Since it's a debugging tool, we
don't want to create false alarms when the occasional packet gets
reordered in a production system, but have this information readily
available when the program's log level is set to debug, instead of
having users fish for it with code instrumentation.

[ RC - corrected printf format for sequence id. ]

Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
2020-06-24 10:09:13 -07:00
Vladimir Oltean 5cca24bc07 ptp4l: call recvmsg() with the MSG_DONTWAIT flag
The application's main event loop (clock_poll) is woken up by poll() and
dispatches the socket receive queue events to the corresponding ports as
needed.

So it is a bug if poll() wakes up the process for data availability on a
socket's receive queue, and then recvmsg(), called immediately
afterwards, goes to sleep trying to retrieve it. This patch will
generate an error that will be propagated to the user if this condition
happens.

Can it happen?

As of this patch, ptp4l uses the SO_SELECT_ERR_QUEUE socket option,
which means that poll() will wake the process up, with revents ==
(POLLIN | POLLERR), if data is available in the error queue. But
clock_poll() does not check POLLERR, just POLLIN, and draws the wrong
conclusion that there is data available in the receive queue (when it is
in fact available in the error queue).

When the above condition happens, recvmsg() will sleep typically for a
whole sync interval waiting for data on the event socket, and will be
woken up when the new real frame arrives. It will not dequeue follow-up
messages during this time (which are sent to the general message socket)
and when it does, it will already be late for them (their seqid will be
out of order). So it will drop them and everything that comes after. The
synchronization process will fail.

The above condition shouldn't typically happen, but exceptional kernel
events will trigger it. It helps to be strict in ptp4l in order for
those events to not blow up in even stranger symptoms unrelated to the
root cause of the problem.

Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
2020-06-24 10:09:13 -07:00
Werner Macho 7c49882e34 fix small typo
Signed-off-by: Werner Macho <werner.macho@gmail.com>
2020-06-15 11:59:47 -07:00
Christian Eggers 7de73fefc3 Fix printf if time_t is long long
On some platforms, time_t has recently switched from "long" to "long
long" [1]. For these platforms it is necessary to use "%lld" as printf
format specifier because the ABI differs between "long" and "long long".

I found no way for creating something similar to PRId64 for time_t. No
idea how to determine whether it's "long" or "long long". So I cast
everything to "long long" instead.

[1] https://git.musl-libc.org/cgit/musl/commit/?id=38143339646a4ccce8afe298c34467767c899f51

Signed-off-by: Christian Eggers <ceggers@arri.de>
2020-06-02 07:36:21 -07:00
Richard Cochran 6eb9898f61 pmc: Show slave delay timing data TLVs attached to signaling messages.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
2020-05-24 19:46:31 -07:00
Richard Cochran 271a6d53f6 port: Support slave event monitoring of delay timing data.
After a successful message exchange, the delay measurement values are
processed by the port code.  This patch makes the values available to a
monitor by calling the appropriate method.

Signed-off-by: Richard Cochran <richardcochran@gmail.com>
2020-05-24 19:46:31 -07:00
Richard Cochran 4466d7b8ab monitor: Add support for slave delay timing data TLV.
The slave delay timing data TLV provides the delay time stamps along with
the associated correction field.  This patch introduces a method to allow
publication of these values to a remote monitor.

Signed-off-by: Richard Cochran <richardcochran@gmail.com>
2020-05-24 19:46:31 -07:00
Richard Cochran ef9d51a47d tlv: Encode and decode SLAVE_DELAY_TIMING_DATA_NP TLVs.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
2020-05-24 19:46:31 -07:00
Richard Cochran 2d2637989c pmc: Show slave receive timing data TLVs attached to signaling messages.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
2020-05-24 19:46:31 -07:00
Richard Cochran 18bd3054ff port: Support slave event monitoring of Sync timing data.
The monitoring module accepts Sync timing events.  This patch hooks up the
port receive path to call into the monitor.

Signed-off-by: Richard Cochran <richardcochran@gmail.com>
2020-05-24 19:46:31 -07:00
Richard Cochran 6f95c2e92c clock: Create a slave event monitor.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
2020-05-24 19:46:31 -07:00
Richard Cochran d3a519e26d Introduce a module for slave event monitoring.
This patch adds a new module for slave event monitoring with its own
configuration option, a UDS address.  If the option is enabled, then
the monitor will send events to the configured address.  The default
setting produces an inactive monitor that does nothing.

Signed-off-by: Richard Cochran <richardcochran@gmail.com>
2020-05-24 19:46:31 -07:00
Richard Cochran d0aa29b932 tlv: Encode and decode SLAVE_RX_SYNC_TIMING_DATA TLVs.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
2020-05-24 18:46:25 -07:00
Richard Cochran b4d3b4126f tlv: Update macro definitions.
The 2019 version of 1588 known as v2.1 introduces new TLV type and
management IDs.  This patch adds the new definitions.

Signed-off-by: Richard Cochran <richardcochran@gmail.com>
2020-05-24 18:46:25 -07:00
Richard Cochran faea24aa32 Reject path trace TLVs with excessive elements.
The current code truncates the size of path trace TLVs which exceed the
expected maximum based on the largest possible message size.  However if
another TLV follows, then a gap would appear, that is, an area in the
message buffer not pointed to by any TLV descriptor.  In order to avoid
forwarding such malformed messages, this patch changes the logic to reject
them.

Signed-off-by: Richard Cochran <richardcochran@gmail.com>
2020-05-24 12:19:58 -07:00
Richard Cochran 8f523e4d62 port: Publish the method for creating signaling messages.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
2020-05-24 12:19:58 -07:00
Richard Cochran 0695d48332 port: Export the value of the wildcard port identity.
Code in other modules will need this special port ID value.  This patch
makes it available through the port header file.

Signed-off-by: Richard Cochran <richardcochran@gmail.com>
2020-05-24 12:19:58 -07:00
Richard Cochran 44c06f5d44 util: Mark port identity comparisons as const.
The utility function to compare port IDs takes pointers, but it only needs
to read the referenced data.  This patch marks the parameters as const,
allowing passing constants in the future.

Signed-off-by: Richard Cochran <richardcochran@gmail.com>
2020-05-24 12:19:58 -07:00
Richard Cochran 5aa19dd3f4 port: Convey targeted forwarding errors to the caller.
The port_forward_to() method clobbers the specific error code returned
by the transport layer with -1.  This patch lets the code preserve the
specific error in question.

Signed-off-by: Richard Cochran <richardcochran@gmail.com>
2020-05-24 12:19:58 -07:00
Richard Cochran a6e0b83bd5 sk: Convey transmit path errors to the caller.
The transport layer's functional interface foresees having error codes
percolate back up to the caller.  However, up until now, the sk module
simply returned -1 for any error.  This patch lets the code return the
specific error instead.

Signed-off-by: Richard Cochran <richardcochran@gmail.com>
2020-05-24 12:19:58 -07:00
Richard Cochran d95fbcb566 raw: Convey transmit path errors to the caller.
The transport layer's functional interface foresees having error codes
percolate back up to the caller.  However, up until now, the raw module
simply returned -1 for any error.  This patch lets the code return the
specific error instead.  In addition, it removes the gratuitous printing
of the error message, leaving that task up to caller, just like the other
transport modules.

Signed-off-by: Richard Cochran <richardcochran@gmail.com>
2020-05-24 12:19:58 -07:00
Richard Cochran 0d82c41ac1 uds: Convey transmit path errors to the caller.
The transport layer's functional interface foresees having error codes
percolate back up to the caller.  However, up until now, the uds module
simply returned -1 for any error.  This patch lets the code return the
specific error instead.  In addition, it removes the gratuitous printing
of the error message, leaving that task up to caller, just like the other
transport modules.

Signed-off-by: Richard Cochran <richardcochran@gmail.com>
2020-05-24 12:19:58 -07:00
Richard Cochran b2bf55aebd udp6: Convey transmit path errors to the caller.
The transport layer's functional interface foresees having error codes
percolate back up to the caller.  However, up until now, the udp6 module
simply returned -1 for any error.  This patch lets the code return the
specific error instead.

Signed-off-by: Richard Cochran <richardcochran@gmail.com>
2020-05-24 12:19:58 -07:00
Richard Cochran d4fbb0701d udp: Convey transmit path errors to the caller.
The transport layer's functional interface foresees having error codes
percolate back up to the caller.  However, up until now, the udp module
simply returned -1 for any error.  This patch lets the code return the
specific error instead.

Signed-off-by: Richard Cochran <richardcochran@gmail.com>
2020-05-24 12:19:58 -07:00
Richard Cochran 306ac67460 transport: Correct grammar in the doxygen comments.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
2020-05-24 12:19:58 -07:00