History

ptp: Support late timestamp determination

If a physical clock supports a free running cycle counter, then timestamps shall be based on this time too. For TX it is known in advance before the transmission if a timestamp based on the free running cycle counter is needed. For RX it is impossible to know which timestamp is needed before the packet is received and assigned to a socket. Support late timestamp determination by a network device. Therefore, an address/cookie is stored within the new netdev_data field of struct skb_shared_hwtstamps. This address/cookie is provided to a new network device function called ndo_get_tstamp(), which returns a timestamp based on the normal/adjustable time or based on the free running cycle counter. If function is not supported, then timestamp handling is not changed. This mechanism is intended for RX, but TX use is also possible.

Gerhard Engleder committed 4 years ago

Commit 97dc7cd1 parent d58809d3 files · +71 −13Browse files

Unified · Split

3 files
  1. include/linux/netdevice.h +21 −0
  2. include/linux/skbuff.h +11 −3
  3. net/socket.c +39 −10
include/linux/netdevice.h+21−0
@@ -1356,6 +1356,12 @@ struct netdev_net_notifier { · 1355 unmodified lines
1356 * The caller must be under RCU read context.1356 * The caller must be under RCU read context.
1357 * int (*ndo_fill_forward_path)(struct net_device_path_ctx *ctx, struct net_device_path *path);1357 * int (*ndo_fill_forward_path)(struct net_device_path_ctx *ctx, struct net_device_path *path);
1358 * Get the forwarding path to reach the real device from the HW destination address1358 * Get the forwarding path to reach the real device from the HW destination address
1359 * ktime_t (*ndo_get_tstamp)(struct net_device *dev,
1360 * const struct skb_shared_hwtstamps *hwtstamps,
1361 * bool cycles);
1362 * Get hardware timestamp based on normal/adjustable time or free running
1363 * cycle counter. This function is required if physical clock supports a
1364 * free running cycle counter.
1359 */1365 */
1360struct net_device_ops {1366struct net_device_ops {
1361 int (*ndo_init)(struct net_device *dev);1367 int (*ndo_init)(struct net_device *dev);
@@ -1578,6 +1584,9 @@ struct net_device_ops { · 216 unmodified lines
1578 struct net_device * (*ndo_get_peer_dev)(struct net_device *dev);1584 struct net_device * (*ndo_get_peer_dev)(struct net_device *dev);
1579 int (*ndo_fill_forward_path)(struct net_device_path_ctx *ctx,1585 int (*ndo_fill_forward_path)(struct net_device_path_ctx *ctx,
1580 struct net_device_path *path);1586 struct net_device_path *path);
1587 ktime_t (*ndo_get_tstamp)(struct net_device *dev,
1588 const struct skb_shared_hwtstamps *hwtstamps,
1589 bool cycles);
1581};1590};
1582 1591
1583/**1592/**
@@ -4761,6 +4770,18 @@ static inline void netdev_rx_csum_fault(struct net_device *dev, · 3177 unmodified lines
4761void net_enable_timestamp(void);4770void net_enable_timestamp(void);
4762void net_disable_timestamp(void);4771void net_disable_timestamp(void);
4763 4772
4773static inline ktime_t netdev_get_tstamp(struct net_device *dev,
4774 const struct skb_shared_hwtstamps *hwtstamps,
4775 bool cycles)
4776{
4777 const struct net_device_ops *ops = dev->netdev_ops;
4778
4779 if (ops->ndo_get_tstamp)
4780 return ops->ndo_get_tstamp(dev, hwtstamps, cycles);
4781
4782 return hwtstamps->hwtstamp;
4783}
4784
4764static inline netdev_tx_t __netdev_start_xmit(const struct net_device_ops *ops,4785static inline netdev_tx_t __netdev_start_xmit(const struct net_device_ops *ops,
4765 struct sk_buff *skb, struct net_device *dev,4786 struct sk_buff *skb, struct net_device *dev,
4766 bool more)4787 bool more)
include/linux/skbuff.h+11−3
@@ -588,8 +588,10 @@ static inline bool skb_frag_must_loop(struct page *p) · 587 unmodified lines
588 588
589/**589/**
590 * struct skb_shared_hwtstamps - hardware time stamps590 * struct skb_shared_hwtstamps - hardware time stamps
591 * @hwtstamp: hardware time stamp transformed into duration591 * @hwtstamp: hardware time stamp transformed into duration
592 * since arbitrary point in time592 * since arbitrary point in time
593 * @netdev_data: address/cookie of network device driver used as
594 * reference to actual hardware time stamp
593 *595 *
594 * Software time stamps generated by ktime_get_real() are stored in596 * Software time stamps generated by ktime_get_real() are stored in
595 * skb->tstamp.597 * skb->tstamp.
@@ -601,7 +603,10 @@ static inline bool skb_frag_must_loop(struct page *p) · 5 unmodified lines
601 * &skb_shared_info. Use skb_hwtstamps() to get a pointer.603 * &skb_shared_info. Use skb_hwtstamps() to get a pointer.
602 */604 */
603struct skb_shared_hwtstamps {605struct skb_shared_hwtstamps {
604 ktime_t hwtstamp;606 union {
607 ktime_t hwtstamp;
608 void *netdev_data;
609 };
605};610};
606 611
607/* Definitions for tx_flags in struct skb_shared_info */612/* Definitions for tx_flags in struct skb_shared_info */
@@ -621,6 +626,9 @@ enum { · 13 unmodified lines
621 /* generate wifi status information (where possible) */626 /* generate wifi status information (where possible) */
622 SKBTX_WIFI_STATUS = 1 << 4,627 SKBTX_WIFI_STATUS = 1 << 4,
623 628
629 /* determine hardware time stamp based on time or cycles */
630 SKBTX_HW_TSTAMP_NETDEV = 1 << 5,
631
624 /* generate software time stamp when entering packet scheduling */632 /* generate software time stamp when entering packet scheduling */
625 SKBTX_SCHED_TSTAMP = 1 << 6,633 SKBTX_SCHED_TSTAMP = 1 << 6,
626};634};
net/socket.c+39−10
@@ -805,7 +805,28 @@ static bool skb_is_swtx_tstamp(const struct sk_buff *skb, int false_tstamp) · 804 unmodified lines
805 return skb->tstamp && !false_tstamp && skb_is_err_queue(skb);805 return skb->tstamp && !false_tstamp && skb_is_err_queue(skb);
806}806}
807 807
808static void put_ts_pktinfo(struct msghdr *msg, struct sk_buff *skb)808static ktime_t get_timestamp(struct sock *sk, struct sk_buff *skb, int *if_index)
809{
810 bool cycles = sk->sk_tsflags & SOF_TIMESTAMPING_BIND_PHC;
811 struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb);
812 struct net_device *orig_dev;
813 ktime_t hwtstamp;
814
815 rcu_read_lock();
816 orig_dev = dev_get_by_napi_id(skb_napi_id(skb));
817 if (orig_dev) {
818 *if_index = orig_dev->ifindex;
819 hwtstamp = netdev_get_tstamp(orig_dev, shhwtstamps, cycles);
820 } else {
821 hwtstamp = shhwtstamps->hwtstamp;
822 }
823 rcu_read_unlock();
824
825 return hwtstamp;
826}
827
828static void put_ts_pktinfo(struct msghdr *msg, struct sk_buff *skb,
829 int if_index)
809{830{
810 struct scm_ts_pktinfo ts_pktinfo;831 struct scm_ts_pktinfo ts_pktinfo;
811 struct net_device *orig_dev;832 struct net_device *orig_dev;
@@ -815,11 +836,14 @@ static void put_ts_pktinfo(struct msghdr *msg, struct sk_buff *skb) · 3 unmodified lines
815 836
816 memset(&ts_pktinfo, 0, sizeof(ts_pktinfo));837 memset(&ts_pktinfo, 0, sizeof(ts_pktinfo));
817 838
818 rcu_read_lock();839 if (!if_index) {
819 orig_dev = dev_get_by_napi_id(skb_napi_id(skb));840 rcu_read_lock();
820 if (orig_dev)841 orig_dev = dev_get_by_napi_id(skb_napi_id(skb));
821 ts_pktinfo.if_index = orig_dev->ifindex;842 if (orig_dev)
822 rcu_read_unlock();843 if_index = orig_dev->ifindex;
844 rcu_read_unlock();
845 }
846 ts_pktinfo.if_index = if_index;
823 847
824 ts_pktinfo.pkt_length = skb->len - skb_mac_offset(skb);848 ts_pktinfo.pkt_length = skb->len - skb_mac_offset(skb);
825 put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING_PKTINFO,849 put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPING_PKTINFO,
@@ -839,6 +863,7 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, · 13 unmodified lines
839 int empty = 1, false_tstamp = 0;863 int empty = 1, false_tstamp = 0;
840 struct skb_shared_hwtstamps *shhwtstamps =864 struct skb_shared_hwtstamps *shhwtstamps =
841 skb_hwtstamps(skb);865 skb_hwtstamps(skb);
866 int if_index;
842 ktime_t hwtstamp;867 ktime_t hwtstamp;
843 868
844 /* Race occurred between timestamp enabling and packet869 /* Race occurred between timestamp enabling and packet
@@ -887,18 +912,22 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, · 42 unmodified lines
887 if (shhwtstamps &&912 if (shhwtstamps &&
888 (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) &&913 (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) &&
889 !skb_is_swtx_tstamp(skb, false_tstamp)) {914 !skb_is_swtx_tstamp(skb, false_tstamp)) {
890 if (sk->sk_tsflags & SOF_TIMESTAMPING_BIND_PHC)915 if_index = 0;
891 hwtstamp = ptp_convert_timestamp(&shhwtstamps->hwtstamp,916 if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP_NETDEV)
892 sk->sk_bind_phc);917 hwtstamp = get_timestamp(sk, skb, &if_index);
893 else918 else
894 hwtstamp = shhwtstamps->hwtstamp;919 hwtstamp = shhwtstamps->hwtstamp;
895 920
921 if (sk->sk_tsflags & SOF_TIMESTAMPING_BIND_PHC)
922 hwtstamp = ptp_convert_timestamp(&hwtstamp,
923 sk->sk_bind_phc);
924
896 if (ktime_to_timespec64_cond(hwtstamp, tss.ts + 2)) {925 if (ktime_to_timespec64_cond(hwtstamp, tss.ts + 2)) {
897 empty = 0;926 empty = 0;
898 927
899 if ((sk->sk_tsflags & SOF_TIMESTAMPING_OPT_PKTINFO) &&928 if ((sk->sk_tsflags & SOF_TIMESTAMPING_OPT_PKTINFO) &&
900 !skb_is_err_queue(skb))929 !skb_is_err_queue(skb))
901 put_ts_pktinfo(msg, skb);930 put_ts_pktinfo(msg, skb, if_index);
902 }931 }
903 }932 }
904 if (!empty) {933 if (!empty) {

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t