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
13561356 * The caller must be under RCU read context.
13571357 * int (*ndo_fill_forward_path)(struct net_device_path_ctx *ctx, struct net_device_path *path);
13581358 * 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.
13591365 */
13601366 struct net_device_ops {
13611367 int (*ndo_init)(struct net_device *dev);
@@ -1578,6 +1584,9 @@ struct net_device_ops { · 216 unmodified lines
15781584 struct net_device * (*ndo_get_peer_dev)(struct net_device *dev);
15791585 int (*ndo_fill_forward_path)(struct net_device_path_ctx *ctx,
15801586 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);
15811590 };
15821591
15831592 /**
@@ -4761,6 +4770,18 @@ static inline void netdev_rx_csum_fault(struct net_device *dev, · 3177 unmodified lines
47614770 void net_enable_timestamp(void);
47624771 void net_disable_timestamp(void);
47634772
4773+static 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+
47644785 static inline netdev_tx_t __netdev_start_xmit(const struct net_device_ops *ops,
47654786 struct sk_buff *skb, struct net_device *dev,
47664787 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
588588
589589 /**
590590 * struct skb_shared_hwtstamps - hardware time stamps
591− * @hwtstamp: hardware time stamp transformed into duration
592− * since arbitrary point in time
591+ * @hwtstamp: hardware time stamp transformed into duration
592+ * since arbitrary point in time
593+ * @netdev_data: address/cookie of network device driver used as
594+ * reference to actual hardware time stamp
593595 *
594596 * Software time stamps generated by ktime_get_real() are stored in
595597 * skb->tstamp.
@@ -601,7 +603,10 @@ static inline bool skb_frag_must_loop(struct page *p) · 5 unmodified lines
601603 * &skb_shared_info. Use skb_hwtstamps() to get a pointer.
602604 */
603605 struct skb_shared_hwtstamps {
604− ktime_t hwtstamp;
606+ union {
607+ ktime_t hwtstamp;
608+ void *netdev_data;
609+ };
605610 };
606611
607612 /* Definitions for tx_flags in struct skb_shared_info */
@@ -621,6 +626,9 @@ enum { · 13 unmodified lines
621626 /* generate wifi status information (where possible) */
622627 SKBTX_WIFI_STATUS = 1 << 4,
623628
629+ /* determine hardware time stamp based on time or cycles */
630+ SKBTX_HW_TSTAMP_NETDEV = 1 << 5,
631+
624632 /* generate software time stamp when entering packet scheduling */
625633 SKBTX_SCHED_TSTAMP = 1 << 6,
626634 };
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
805805 return skb->tstamp && !false_tstamp && skb_is_err_queue(skb);
806806 }
807807
808−static void put_ts_pktinfo(struct msghdr *msg, struct sk_buff *skb)
808+static 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+
828+static void put_ts_pktinfo(struct msghdr *msg, struct sk_buff *skb,
829+ int if_index)
809830 {
810831 struct scm_ts_pktinfo ts_pktinfo;
811832 struct net_device *orig_dev;
@@ -815,11 +836,14 @@ static void put_ts_pktinfo(struct msghdr *msg, struct sk_buff *skb) · 3 unmodified lines
815836
816837 memset(&ts_pktinfo, 0, sizeof(ts_pktinfo));
817838
818− rcu_read_lock();
819− orig_dev = dev_get_by_napi_id(skb_napi_id(skb));
820− if (orig_dev)
821− ts_pktinfo.if_index = orig_dev->ifindex;
822− rcu_read_unlock();
839+ if (!if_index) {
840+ rcu_read_lock();
841+ orig_dev = dev_get_by_napi_id(skb_napi_id(skb));
842+ if (orig_dev)
843+ if_index = orig_dev->ifindex;
844+ rcu_read_unlock();
845+ }
846+ ts_pktinfo.if_index = if_index;
823847
824848 ts_pktinfo.pkt_length = skb->len - skb_mac_offset(skb);
825849 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
839863 int empty = 1, false_tstamp = 0;
840864 struct skb_shared_hwtstamps *shhwtstamps =
841865 skb_hwtstamps(skb);
866+ int if_index;
842867 ktime_t hwtstamp;
843868
844869 /* Race occurred between timestamp enabling and packet
@@ -887,18 +912,22 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, · 42 unmodified lines
887912 if (shhwtstamps &&
888913 (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) &&
889914 !skb_is_swtx_tstamp(skb, false_tstamp)) {
890− if (sk->sk_tsflags & SOF_TIMESTAMPING_BIND_PHC)
891− hwtstamp = ptp_convert_timestamp(&shhwtstamps->hwtstamp,
892− sk->sk_bind_phc);
915+ if_index = 0;
916+ if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP_NETDEV)
917+ hwtstamp = get_timestamp(sk, skb, &if_index);
893918 else
894919 hwtstamp = shhwtstamps->hwtstamp;
895920
921+ if (sk->sk_tsflags & SOF_TIMESTAMPING_BIND_PHC)
922+ hwtstamp = ptp_convert_timestamp(&hwtstamp,
923+ sk->sk_bind_phc);
924+
896925 if (ktime_to_timespec64_cond(hwtstamp, tss.ts + 2)) {
897926 empty = 0;
898927
899928 if ((sk->sk_tsflags & SOF_TIMESTAMPING_OPT_PKTINFO) &&
900929 !skb_is_err_queue(skb))
901− put_ts_pktinfo(msg, skb);
930+ put_ts_pktinfo(msg, skb, if_index);
902931 }
903932 }
904933 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