Patrick Ohly | cb9eff0 | 2009-02-12 05:03:36 +0000 | [diff] [blame] | 1 | The existing interfaces for getting network packages time stamped are: |
| 2 | |
| 3 | * SO_TIMESTAMP |
| 4 | Generate time stamp for each incoming packet using the (not necessarily |
| 5 | monotonous!) system time. Result is returned via recv_msg() in a |
| 6 | control message as timeval (usec resolution). |
| 7 | |
| 8 | * SO_TIMESTAMPNS |
| 9 | Same time stamping mechanism as SO_TIMESTAMP, but returns result as |
| 10 | timespec (nsec resolution). |
| 11 | |
| 12 | * IP_MULTICAST_LOOP + SO_TIMESTAMP[NS] |
| 13 | Only for multicasts: approximate send time stamp by receiving the looped |
| 14 | packet and using its receive time stamp. |
| 15 | |
| 16 | The following interface complements the existing ones: receive time |
| 17 | stamps can be generated and returned for arbitrary packets and much |
| 18 | closer to the point where the packet is really sent. Time stamps can |
| 19 | be generated in software (as before) or in hardware (if the hardware |
| 20 | has such a feature). |
| 21 | |
| 22 | SO_TIMESTAMPING: |
| 23 | |
Andrew Lutomirski | adca476 | 2014-03-04 17:24:10 -0800 | [diff] [blame] | 24 | Instructs the socket layer which kind of information should be collected |
| 25 | and/or reported. The parameter is an integer with some of the following |
| 26 | bits set. Setting other bits is an error and doesn't change the current |
| 27 | state. |
Patrick Ohly | cb9eff0 | 2009-02-12 05:03:36 +0000 | [diff] [blame] | 28 | |
Andrew Lutomirski | adca476 | 2014-03-04 17:24:10 -0800 | [diff] [blame] | 29 | Four of the bits are requests to the stack to try to generate |
| 30 | timestamps. Any combination of them is valid. |
Patrick Ohly | cb9eff0 | 2009-02-12 05:03:36 +0000 | [diff] [blame] | 31 | |
Andrew Lutomirski | adca476 | 2014-03-04 17:24:10 -0800 | [diff] [blame] | 32 | SOF_TIMESTAMPING_TX_HARDWARE: try to obtain send time stamps in hardware |
| 33 | SOF_TIMESTAMPING_TX_SOFTWARE: try to obtain send time stamps in software |
| 34 | SOF_TIMESTAMPING_RX_HARDWARE: try to obtain receive time stamps in hardware |
| 35 | SOF_TIMESTAMPING_RX_SOFTWARE: try to obtain receive time stamps in software |
| 36 | |
| 37 | The other three bits control which timestamps will be reported in a |
| 38 | generated control message. If none of these bits are set or if none of |
| 39 | the set bits correspond to data that is available, then the control |
| 40 | message will not be generated: |
| 41 | |
| 42 | SOF_TIMESTAMPING_SOFTWARE: report systime if available |
| 43 | SOF_TIMESTAMPING_SYS_HARDWARE: report hwtimetrans if available |
| 44 | SOF_TIMESTAMPING_RAW_HARDWARE: report hwtimeraw if available |
| 45 | |
| 46 | It is worth noting that timestamps may be collected for reasons other |
| 47 | than being requested by a particular socket with |
| 48 | SOF_TIMESTAMPING_[TR]X_(HARD|SOFT)WARE. For example, most drivers that |
| 49 | can generate hardware receive timestamps ignore |
| 50 | SOF_TIMESTAMPING_RX_HARDWARE. It is still a good idea to set that flag |
| 51 | in case future drivers pay attention. |
| 52 | |
| 53 | If timestamps are reported, they will appear in a control message with |
| 54 | cmsg_level==SOL_SOCKET, cmsg_type==SO_TIMESTAMPING, and a payload like |
| 55 | this: |
Patrick Loschmidt | 6929869 | 2010-04-07 21:52:07 -0700 | [diff] [blame] | 56 | |
| 57 | struct scm_timestamping { |
| 58 | struct timespec systime; |
| 59 | struct timespec hwtimetrans; |
| 60 | struct timespec hwtimeraw; |
| 61 | }; |
Patrick Ohly | cb9eff0 | 2009-02-12 05:03:36 +0000 | [diff] [blame] | 62 | |
| 63 | recvmsg() can be used to get this control message for regular incoming |
| 64 | packets. For send time stamps the outgoing packet is looped back to |
| 65 | the socket's error queue with the send time stamp(s) attached. It can |
| 66 | be received with recvmsg(flags=MSG_ERRQUEUE). The call returns the |
| 67 | original outgoing packet data including all headers preprended down to |
| 68 | and including the link layer, the scm_timestamping control message and |
| 69 | a sock_extended_err control message with ee_errno==ENOMSG and |
| 70 | ee_origin==SO_EE_ORIGIN_TIMESTAMPING. A socket with such a pending |
| 71 | bounced packet is ready for reading as far as select() is concerned. |
Patrick Ohly | 51f31ca | 2009-02-12 05:03:39 +0000 | [diff] [blame] | 72 | If the outgoing packet has to be fragmented, then only the first |
| 73 | fragment is time stamped and returned to the sending socket. |
Patrick Ohly | cb9eff0 | 2009-02-12 05:03:36 +0000 | [diff] [blame] | 74 | |
| 75 | All three values correspond to the same event in time, but were |
| 76 | generated in different ways. Each of these values may be empty (= all |
| 77 | zero), in which case no such value was available. If the application |
| 78 | is not interested in some of these values, they can be left blank to |
| 79 | avoid the potential overhead of calculating them. |
| 80 | |
| 81 | systime is the value of the system time at that moment. This |
| 82 | corresponds to the value also returned via SO_TIMESTAMP[NS]. If the |
| 83 | time stamp was generated by hardware, then this field is |
| 84 | empty. Otherwise it is filled in if SOF_TIMESTAMPING_SOFTWARE is |
| 85 | set. |
| 86 | |
| 87 | hwtimeraw is the original hardware time stamp. Filled in if |
| 88 | SOF_TIMESTAMPING_RAW_HARDWARE is set. No assumptions about its |
| 89 | relation to system time should be made. |
| 90 | |
| 91 | hwtimetrans is the hardware time stamp transformed so that it |
| 92 | corresponds as good as possible to system time. This correlation is |
| 93 | not perfect; as a consequence, sorting packets received via different |
| 94 | NICs by their hwtimetrans may differ from the order in which they were |
| 95 | received. hwtimetrans may be non-monotonic even for the same NIC. |
| 96 | Filled in if SOF_TIMESTAMPING_SYS_HARDWARE is set. Requires support |
| 97 | by the network device and will be empty without that support. |
| 98 | |
| 99 | |
Ben Hutchings | fd468c7 | 2013-11-14 01:19:29 +0000 | [diff] [blame] | 100 | SIOCSHWTSTAMP, SIOCGHWTSTAMP: |
Patrick Ohly | cb9eff0 | 2009-02-12 05:03:36 +0000 | [diff] [blame] | 101 | |
| 102 | Hardware time stamping must also be initialized for each device driver |
Patrick Loschmidt | 6929869 | 2010-04-07 21:52:07 -0700 | [diff] [blame] | 103 | that is expected to do hardware time stamping. The parameter is defined in |
| 104 | /include/linux/net_tstamp.h as: |
Patrick Ohly | cb9eff0 | 2009-02-12 05:03:36 +0000 | [diff] [blame] | 105 | |
| 106 | struct hwtstamp_config { |
Patrick Loschmidt | 6929869 | 2010-04-07 21:52:07 -0700 | [diff] [blame] | 107 | int flags; /* no flags defined right now, must be zero */ |
| 108 | int tx_type; /* HWTSTAMP_TX_* */ |
| 109 | int rx_filter; /* HWTSTAMP_FILTER_* */ |
Patrick Ohly | cb9eff0 | 2009-02-12 05:03:36 +0000 | [diff] [blame] | 110 | }; |
| 111 | |
| 112 | Desired behavior is passed into the kernel and to a specific device by |
| 113 | calling ioctl(SIOCSHWTSTAMP) with a pointer to a struct ifreq whose |
| 114 | ifr_data points to a struct hwtstamp_config. The tx_type and |
| 115 | rx_filter are hints to the driver what it is expected to do. If |
| 116 | the requested fine-grained filtering for incoming packets is not |
| 117 | supported, the driver may time stamp more than just the requested types |
| 118 | of packets. |
| 119 | |
| 120 | A driver which supports hardware time stamping shall update the struct |
| 121 | with the actual, possibly more permissive configuration. If the |
| 122 | requested packets cannot be time stamped, then nothing should be |
| 123 | changed and ERANGE shall be returned (in contrast to EINVAL, which |
| 124 | indicates that SIOCSHWTSTAMP is not supported at all). |
| 125 | |
| 126 | Only a processes with admin rights may change the configuration. User |
| 127 | space is responsible to ensure that multiple processes don't interfere |
| 128 | with each other and that the settings are reset. |
| 129 | |
Ben Hutchings | fd468c7 | 2013-11-14 01:19:29 +0000 | [diff] [blame] | 130 | Any process can read the actual configuration by passing this |
| 131 | structure to ioctl(SIOCGHWTSTAMP) in the same way. However, this has |
| 132 | not been implemented in all drivers. |
| 133 | |
Patrick Ohly | cb9eff0 | 2009-02-12 05:03:36 +0000 | [diff] [blame] | 134 | /* possible values for hwtstamp_config->tx_type */ |
| 135 | enum { |
| 136 | /* |
| 137 | * no outgoing packet will need hardware time stamping; |
| 138 | * should a packet arrive which asks for it, no hardware |
| 139 | * time stamping will be done |
| 140 | */ |
| 141 | HWTSTAMP_TX_OFF, |
| 142 | |
| 143 | /* |
| 144 | * enables hardware time stamping for outgoing packets; |
| 145 | * the sender of the packet decides which are to be |
| 146 | * time stamped by setting SOF_TIMESTAMPING_TX_SOFTWARE |
| 147 | * before sending the packet |
| 148 | */ |
| 149 | HWTSTAMP_TX_ON, |
| 150 | }; |
| 151 | |
| 152 | /* possible values for hwtstamp_config->rx_filter */ |
| 153 | enum { |
| 154 | /* time stamp no incoming packet at all */ |
| 155 | HWTSTAMP_FILTER_NONE, |
| 156 | |
| 157 | /* time stamp any incoming packet */ |
| 158 | HWTSTAMP_FILTER_ALL, |
| 159 | |
Patrick Loschmidt | 6929869 | 2010-04-07 21:52:07 -0700 | [diff] [blame] | 160 | /* return value: time stamp all packets requested plus some others */ |
| 161 | HWTSTAMP_FILTER_SOME, |
Patrick Ohly | cb9eff0 | 2009-02-12 05:03:36 +0000 | [diff] [blame] | 162 | |
| 163 | /* PTP v1, UDP, any kind of event packet */ |
| 164 | HWTSTAMP_FILTER_PTP_V1_L4_EVENT, |
| 165 | |
Patrick Loschmidt | 6929869 | 2010-04-07 21:52:07 -0700 | [diff] [blame] | 166 | /* for the complete list of values, please check |
| 167 | * the include file /include/linux/net_tstamp.h |
| 168 | */ |
Patrick Ohly | cb9eff0 | 2009-02-12 05:03:36 +0000 | [diff] [blame] | 169 | }; |
| 170 | |
| 171 | |
| 172 | DEVICE IMPLEMENTATION |
| 173 | |
| 174 | A driver which supports hardware time stamping must support the |
Patrick Loschmidt | 6929869 | 2010-04-07 21:52:07 -0700 | [diff] [blame] | 175 | SIOCSHWTSTAMP ioctl and update the supplied struct hwtstamp_config with |
Ben Hutchings | fd468c7 | 2013-11-14 01:19:29 +0000 | [diff] [blame] | 176 | the actual values as described in the section on SIOCSHWTSTAMP. It |
| 177 | should also support SIOCGHWTSTAMP. |
Patrick Loschmidt | 6929869 | 2010-04-07 21:52:07 -0700 | [diff] [blame] | 178 | |
| 179 | Time stamps for received packets must be stored in the skb. To get a pointer |
| 180 | to the shared time stamp structure of the skb call skb_hwtstamps(). Then |
| 181 | set the time stamps in the structure: |
| 182 | |
| 183 | struct skb_shared_hwtstamps { |
| 184 | /* hardware time stamp transformed into duration |
| 185 | * since arbitrary point in time |
| 186 | */ |
| 187 | ktime_t hwtstamp; |
| 188 | ktime_t syststamp; /* hwtstamp transformed to system time base */ |
| 189 | }; |
Patrick Ohly | cb9eff0 | 2009-02-12 05:03:36 +0000 | [diff] [blame] | 190 | |
| 191 | Time stamps for outgoing packets are to be generated as follows: |
Oliver Hartkopp | 2244d07 | 2010-08-17 08:59:14 +0000 | [diff] [blame] | 192 | - In hard_start_xmit(), check if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) |
| 193 | is set no-zero. If yes, then the driver is expected to do hardware time |
| 194 | stamping. |
Patrick Ohly | cb9eff0 | 2009-02-12 05:03:36 +0000 | [diff] [blame] | 195 | - If this is possible for the skb and requested, then declare |
Oliver Hartkopp | 2244d07 | 2010-08-17 08:59:14 +0000 | [diff] [blame] | 196 | that the driver is doing the time stamping by setting the flag |
| 197 | SKBTX_IN_PROGRESS in skb_shinfo(skb)->tx_flags , e.g. with |
| 198 | |
| 199 | skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; |
| 200 | |
| 201 | You might want to keep a pointer to the associated skb for the next step |
| 202 | and not free the skb. A driver not supporting hardware time stamping doesn't |
| 203 | do that. A driver must never touch sk_buff::tstamp! It is used to store |
| 204 | software generated time stamps by the network subsystem. |
Jakub Kicinski | 59cb89e | 2014-03-16 20:32:48 +0100 | [diff] [blame] | 205 | - Driver should call skb_tx_timestamp() as close to passing sk_buff to hardware |
| 206 | as possible. skb_tx_timestamp() provides a software time stamp if requested |
| 207 | and hardware timestamping is not possible (SKBTX_IN_PROGRESS not set). |
Patrick Ohly | cb9eff0 | 2009-02-12 05:03:36 +0000 | [diff] [blame] | 208 | - As soon as the driver has sent the packet and/or obtained a |
| 209 | hardware time stamp for it, it passes the time stamp back by |
| 210 | calling skb_hwtstamp_tx() with the original skb, the raw |
Patrick Loschmidt | 6929869 | 2010-04-07 21:52:07 -0700 | [diff] [blame] | 211 | hardware time stamp. skb_hwtstamp_tx() clones the original skb and |
| 212 | adds the timestamps, therefore the original skb has to be freed now. |
| 213 | If obtaining the hardware time stamp somehow fails, then the driver |
| 214 | should not fall back to software time stamping. The rationale is that |
| 215 | this would occur at a later time in the processing pipeline than other |
| 216 | software time stamping and therefore could lead to unexpected deltas |
| 217 | between time stamps. |