123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- The existing interfaces for getting network packages time stamped are:
- * SO_TIMESTAMP
- Generate time stamp for each incoming packet using the (not necessarily
- monotonous!) system time. Result is returned via recv_msg() in a
- control message as timeval (usec resolution).
- * SO_TIMESTAMPNS
- Same time stamping mechanism as SO_TIMESTAMP, but returns result as
- timespec (nsec resolution).
- * IP_MULTICAST_LOOP + SO_TIMESTAMP[NS]
- Only for multicasts: approximate send time stamp by receiving the looped
- packet and using its receive time stamp.
- The following interface complements the existing ones: receive time
- stamps can be generated and returned for arbitrary packets and much
- closer to the point where the packet is really sent. Time stamps can
- be generated in software (as before) or in hardware (if the hardware
- has such a feature).
- SO_TIMESTAMPING:
- Instructs the socket layer which kind of information is wanted. The
- parameter is an integer with some of the following bits set. Setting
- other bits is an error and doesn't change the current state.
- SOF_TIMESTAMPING_TX_HARDWARE: try to obtain send time stamp in hardware
- SOF_TIMESTAMPING_TX_SOFTWARE: if SOF_TIMESTAMPING_TX_HARDWARE is off or
- fails, then do it in software
- SOF_TIMESTAMPING_RX_HARDWARE: return the original, unmodified time stamp
- as generated by the hardware
- SOF_TIMESTAMPING_RX_SOFTWARE: if SOF_TIMESTAMPING_RX_HARDWARE is off or
- fails, then do it in software
- SOF_TIMESTAMPING_RAW_HARDWARE: return original raw hardware time stamp
- SOF_TIMESTAMPING_SYS_HARDWARE: return hardware time stamp transformed to
- the system time base
- SOF_TIMESTAMPING_SOFTWARE: return system time stamp generated in
- software
- SOF_TIMESTAMPING_TX/RX determine how time stamps are generated.
- SOF_TIMESTAMPING_RAW/SYS determine how they are reported in the
- following control message:
- struct scm_timestamping {
- struct timespec systime;
- struct timespec hwtimetrans;
- struct timespec hwtimeraw;
- };
- recvmsg() can be used to get this control message for regular incoming
- packets. For send time stamps the outgoing packet is looped back to
- the socket's error queue with the send time stamp(s) attached. It can
- be received with recvmsg(flags=MSG_ERRQUEUE). The call returns the
- original outgoing packet data including all headers preprended down to
- and including the link layer, the scm_timestamping control message and
- a sock_extended_err control message with ee_errno==ENOMSG and
- ee_origin==SO_EE_ORIGIN_TIMESTAMPING. A socket with such a pending
- bounced packet is ready for reading as far as select() is concerned.
- If the outgoing packet has to be fragmented, then only the first
- fragment is time stamped and returned to the sending socket.
- All three values correspond to the same event in time, but were
- generated in different ways. Each of these values may be empty (= all
- zero), in which case no such value was available. If the application
- is not interested in some of these values, they can be left blank to
- avoid the potential overhead of calculating them.
- systime is the value of the system time at that moment. This
- corresponds to the value also returned via SO_TIMESTAMP[NS]. If the
- time stamp was generated by hardware, then this field is
- empty. Otherwise it is filled in if SOF_TIMESTAMPING_SOFTWARE is
- set.
- hwtimeraw is the original hardware time stamp. Filled in if
- SOF_TIMESTAMPING_RAW_HARDWARE is set. No assumptions about its
- relation to system time should be made.
- hwtimetrans is the hardware time stamp transformed so that it
- corresponds as good as possible to system time. This correlation is
- not perfect; as a consequence, sorting packets received via different
- NICs by their hwtimetrans may differ from the order in which they were
- received. hwtimetrans may be non-monotonic even for the same NIC.
- Filled in if SOF_TIMESTAMPING_SYS_HARDWARE is set. Requires support
- by the network device and will be empty without that support.
- SIOCSHWTSTAMP:
- Hardware time stamping must also be initialized for each device driver
- that is expected to do hardware time stamping. The parameter is defined in
- /include/linux/net_tstamp.h as:
- struct hwtstamp_config {
- int flags; /* no flags defined right now, must be zero */
- int tx_type; /* HWTSTAMP_TX_* */
- int rx_filter; /* HWTSTAMP_FILTER_* */
- };
- Desired behavior is passed into the kernel and to a specific device by
- calling ioctl(SIOCSHWTSTAMP) with a pointer to a struct ifreq whose
- ifr_data points to a struct hwtstamp_config. The tx_type and
- rx_filter are hints to the driver what it is expected to do. If
- the requested fine-grained filtering for incoming packets is not
- supported, the driver may time stamp more than just the requested types
- of packets.
- A driver which supports hardware time stamping shall update the struct
- with the actual, possibly more permissive configuration. If the
- requested packets cannot be time stamped, then nothing should be
- changed and ERANGE shall be returned (in contrast to EINVAL, which
- indicates that SIOCSHWTSTAMP is not supported at all).
- Only a processes with admin rights may change the configuration. User
- space is responsible to ensure that multiple processes don't interfere
- with each other and that the settings are reset.
- /* possible values for hwtstamp_config->tx_type */
- enum {
- /*
- * no outgoing packet will need hardware time stamping;
- * should a packet arrive which asks for it, no hardware
- * time stamping will be done
- */
- HWTSTAMP_TX_OFF,
- /*
- * enables hardware time stamping for outgoing packets;
- * the sender of the packet decides which are to be
- * time stamped by setting SOF_TIMESTAMPING_TX_SOFTWARE
- * before sending the packet
- */
- HWTSTAMP_TX_ON,
- };
- /* possible values for hwtstamp_config->rx_filter */
- enum {
- /* time stamp no incoming packet at all */
- HWTSTAMP_FILTER_NONE,
- /* time stamp any incoming packet */
- HWTSTAMP_FILTER_ALL,
- /* return value: time stamp all packets requested plus some others */
- HWTSTAMP_FILTER_SOME,
- /* PTP v1, UDP, any kind of event packet */
- HWTSTAMP_FILTER_PTP_V1_L4_EVENT,
- /* for the complete list of values, please check
- * the include file /include/linux/net_tstamp.h
- */
- };
- DEVICE IMPLEMENTATION
- A driver which supports hardware time stamping must support the
- SIOCSHWTSTAMP ioctl and update the supplied struct hwtstamp_config with
- the actual values as described in the section on SIOCSHWTSTAMP.
- Time stamps for received packets must be stored in the skb. To get a pointer
- to the shared time stamp structure of the skb call skb_hwtstamps(). Then
- set the time stamps in the structure:
- struct skb_shared_hwtstamps {
- /* hardware time stamp transformed into duration
- * since arbitrary point in time
- */
- ktime_t hwtstamp;
- ktime_t syststamp; /* hwtstamp transformed to system time base */
- };
- Time stamps for outgoing packets are to be generated as follows:
- - In hard_start_xmit(), check if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)
- is set no-zero. If yes, then the driver is expected to do hardware time
- stamping.
- - If this is possible for the skb and requested, then declare
- that the driver is doing the time stamping by setting the flag
- SKBTX_IN_PROGRESS in skb_shinfo(skb)->tx_flags , e.g. with
- skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
- You might want to keep a pointer to the associated skb for the next step
- and not free the skb. A driver not supporting hardware time stamping doesn't
- do that. A driver must never touch sk_buff::tstamp! It is used to store
- software generated time stamps by the network subsystem.
- - As soon as the driver has sent the packet and/or obtained a
- hardware time stamp for it, it passes the time stamp back by
- calling skb_hwtstamp_tx() with the original skb, the raw
- hardware time stamp. skb_hwtstamp_tx() clones the original skb and
- adds the timestamps, therefore the original skb has to be freed now.
- If obtaining the hardware time stamp somehow fails, then the driver
- should not fall back to software time stamping. The rationale is that
- this would occur at a later time in the processing pipeline than other
- software time stamping and therefore could lead to unexpected deltas
- between time stamps.
- - If the driver did not set the SKBTX_IN_PROGRESS flag (see above), then
- dev_hard_start_xmit() checks whether software time stamping
- is wanted as fallback and potentially generates the time stamp.
|