| 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 |  | 
|  | 24 | Instructs the socket layer which kind of information is wanted. The | 
|  | 25 | parameter is an integer with some of the following bits set. Setting | 
|  | 26 | other bits is an error and doesn't change the current state. | 
|  | 27 |  | 
|  | 28 | SOF_TIMESTAMPING_TX_HARDWARE:  try to obtain send time stamp in hardware | 
|  | 29 | SOF_TIMESTAMPING_TX_SOFTWARE:  if SOF_TIMESTAMPING_TX_HARDWARE is off or | 
|  | 30 | fails, then do it in software | 
|  | 31 | SOF_TIMESTAMPING_RX_HARDWARE:  return the original, unmodified time stamp | 
|  | 32 | as generated by the hardware | 
|  | 33 | SOF_TIMESTAMPING_RX_SOFTWARE:  if SOF_TIMESTAMPING_RX_HARDWARE is off or | 
|  | 34 | fails, then do it in software | 
|  | 35 | SOF_TIMESTAMPING_RAW_HARDWARE: return original raw hardware time stamp | 
|  | 36 | SOF_TIMESTAMPING_SYS_HARDWARE: return hardware time stamp transformed to | 
|  | 37 | the system time base | 
|  | 38 | SOF_TIMESTAMPING_SOFTWARE:     return system time stamp generated in | 
|  | 39 | software | 
|  | 40 |  | 
|  | 41 | SOF_TIMESTAMPING_TX/RX determine how time stamps are generated. | 
|  | 42 | SOF_TIMESTAMPING_RAW/SYS determine how they are reported in the | 
|  | 43 | following control message: | 
|  | 44 | struct scm_timestamping { | 
|  | 45 | struct timespec systime; | 
|  | 46 | struct timespec hwtimetrans; | 
|  | 47 | struct timespec hwtimeraw; | 
|  | 48 | }; | 
|  | 49 |  | 
|  | 50 | recvmsg() can be used to get this control message for regular incoming | 
|  | 51 | packets. For send time stamps the outgoing packet is looped back to | 
|  | 52 | the socket's error queue with the send time stamp(s) attached. It can | 
|  | 53 | be received with recvmsg(flags=MSG_ERRQUEUE). The call returns the | 
|  | 54 | original outgoing packet data including all headers preprended down to | 
|  | 55 | and including the link layer, the scm_timestamping control message and | 
|  | 56 | a sock_extended_err control message with ee_errno==ENOMSG and | 
|  | 57 | ee_origin==SO_EE_ORIGIN_TIMESTAMPING. A socket with such a pending | 
|  | 58 | bounced packet is ready for reading as far as select() is concerned. | 
| Patrick Ohly | 51f31ca | 2009-02-12 05:03:39 +0000 | [diff] [blame] | 59 | If the outgoing packet has to be fragmented, then only the first | 
|  | 60 | fragment is time stamped and returned to the sending socket. | 
| Patrick Ohly | cb9eff0 | 2009-02-12 05:03:36 +0000 | [diff] [blame] | 61 |  | 
|  | 62 | All three values correspond to the same event in time, but were | 
|  | 63 | generated in different ways. Each of these values may be empty (= all | 
|  | 64 | zero), in which case no such value was available. If the application | 
|  | 65 | is not interested in some of these values, they can be left blank to | 
|  | 66 | avoid the potential overhead of calculating them. | 
|  | 67 |  | 
|  | 68 | systime is the value of the system time at that moment. This | 
|  | 69 | corresponds to the value also returned via SO_TIMESTAMP[NS]. If the | 
|  | 70 | time stamp was generated by hardware, then this field is | 
|  | 71 | empty. Otherwise it is filled in if SOF_TIMESTAMPING_SOFTWARE is | 
|  | 72 | set. | 
|  | 73 |  | 
|  | 74 | hwtimeraw is the original hardware time stamp. Filled in if | 
|  | 75 | SOF_TIMESTAMPING_RAW_HARDWARE is set. No assumptions about its | 
|  | 76 | relation to system time should be made. | 
|  | 77 |  | 
|  | 78 | hwtimetrans is the hardware time stamp transformed so that it | 
|  | 79 | corresponds as good as possible to system time. This correlation is | 
|  | 80 | not perfect; as a consequence, sorting packets received via different | 
|  | 81 | NICs by their hwtimetrans may differ from the order in which they were | 
|  | 82 | received. hwtimetrans may be non-monotonic even for the same NIC. | 
|  | 83 | Filled in if SOF_TIMESTAMPING_SYS_HARDWARE is set. Requires support | 
|  | 84 | by the network device and will be empty without that support. | 
|  | 85 |  | 
|  | 86 |  | 
|  | 87 | SIOCSHWTSTAMP: | 
|  | 88 |  | 
|  | 89 | Hardware time stamping must also be initialized for each device driver | 
|  | 90 | that is expected to do hardware time stamping. The parameter is: | 
|  | 91 |  | 
|  | 92 | struct hwtstamp_config { | 
|  | 93 | int flags;           /* no flags defined right now, must be zero */ | 
|  | 94 | int tx_type;         /* HWTSTAMP_TX_* */ | 
|  | 95 | int rx_filter;       /* HWTSTAMP_FILTER_* */ | 
|  | 96 | }; | 
|  | 97 |  | 
|  | 98 | Desired behavior is passed into the kernel and to a specific device by | 
|  | 99 | calling ioctl(SIOCSHWTSTAMP) with a pointer to a struct ifreq whose | 
|  | 100 | ifr_data points to a struct hwtstamp_config. The tx_type and | 
|  | 101 | rx_filter are hints to the driver what it is expected to do. If | 
|  | 102 | the requested fine-grained filtering for incoming packets is not | 
|  | 103 | supported, the driver may time stamp more than just the requested types | 
|  | 104 | of packets. | 
|  | 105 |  | 
|  | 106 | A driver which supports hardware time stamping shall update the struct | 
|  | 107 | with the actual, possibly more permissive configuration. If the | 
|  | 108 | requested packets cannot be time stamped, then nothing should be | 
|  | 109 | changed and ERANGE shall be returned (in contrast to EINVAL, which | 
|  | 110 | indicates that SIOCSHWTSTAMP is not supported at all). | 
|  | 111 |  | 
|  | 112 | Only a processes with admin rights may change the configuration. User | 
|  | 113 | space is responsible to ensure that multiple processes don't interfere | 
|  | 114 | with each other and that the settings are reset. | 
|  | 115 |  | 
|  | 116 | /* possible values for hwtstamp_config->tx_type */ | 
|  | 117 | enum { | 
|  | 118 | /* | 
|  | 119 | * no outgoing packet will need hardware time stamping; | 
|  | 120 | * should a packet arrive which asks for it, no hardware | 
|  | 121 | * time stamping will be done | 
|  | 122 | */ | 
|  | 123 | HWTSTAMP_TX_OFF, | 
|  | 124 |  | 
|  | 125 | /* | 
|  | 126 | * enables hardware time stamping for outgoing packets; | 
|  | 127 | * the sender of the packet decides which are to be | 
|  | 128 | * time stamped by setting SOF_TIMESTAMPING_TX_SOFTWARE | 
|  | 129 | * before sending the packet | 
|  | 130 | */ | 
|  | 131 | HWTSTAMP_TX_ON, | 
|  | 132 | }; | 
|  | 133 |  | 
|  | 134 | /* possible values for hwtstamp_config->rx_filter */ | 
|  | 135 | enum { | 
|  | 136 | /* time stamp no incoming packet at all */ | 
|  | 137 | HWTSTAMP_FILTER_NONE, | 
|  | 138 |  | 
|  | 139 | /* time stamp any incoming packet */ | 
|  | 140 | HWTSTAMP_FILTER_ALL, | 
|  | 141 |  | 
|  | 142 | /* return value: time stamp all packets requested plus some others */ | 
|  | 143 | HWTSTAMP_FILTER_SOME, | 
|  | 144 |  | 
|  | 145 | /* PTP v1, UDP, any kind of event packet */ | 
|  | 146 | HWTSTAMP_FILTER_PTP_V1_L4_EVENT, | 
|  | 147 |  | 
|  | 148 | ... | 
|  | 149 | }; | 
|  | 150 |  | 
|  | 151 |  | 
|  | 152 | DEVICE IMPLEMENTATION | 
|  | 153 |  | 
|  | 154 | A driver which supports hardware time stamping must support the | 
|  | 155 | SIOCSHWTSTAMP ioctl. Time stamps for received packets must be stored | 
|  | 156 | in the skb with skb_hwtstamp_set(). | 
|  | 157 |  | 
|  | 158 | Time stamps for outgoing packets are to be generated as follows: | 
|  | 159 | - In hard_start_xmit(), check if skb_hwtstamp_check_tx_hardware() | 
|  | 160 | returns non-zero. If yes, then the driver is expected | 
|  | 161 | to do hardware time stamping. | 
|  | 162 | - If this is possible for the skb and requested, then declare | 
|  | 163 | that the driver is doing the time stamping by calling | 
|  | 164 | skb_hwtstamp_tx_in_progress(). A driver not supporting | 
|  | 165 | hardware time stamping doesn't do that. A driver must never | 
|  | 166 | touch sk_buff::tstamp! It is used to store how time stamping | 
|  | 167 | for an outgoing packets is to be done. | 
|  | 168 | - As soon as the driver has sent the packet and/or obtained a | 
|  | 169 | hardware time stamp for it, it passes the time stamp back by | 
|  | 170 | calling skb_hwtstamp_tx() with the original skb, the raw | 
|  | 171 | hardware time stamp and a handle to the device (necessary | 
|  | 172 | to convert the hardware time stamp to system time). If obtaining | 
|  | 173 | the hardware time stamp somehow fails, then the driver should | 
|  | 174 | not fall back to software time stamping. The rationale is that | 
|  | 175 | this would occur at a later time in the processing pipeline | 
|  | 176 | than other software time stamping and therefore could lead | 
|  | 177 | to unexpected deltas between time stamps. | 
|  | 178 | - If the driver did not call skb_hwtstamp_tx_in_progress(), then | 
|  | 179 | dev_hard_start_xmit() checks whether software time stamping | 
|  | 180 | is wanted as fallback and potentially generates the time stamp. |