Commit f0a03a02 authored by Jesse Brandeburg's avatar Jesse Brandeburg Committed by Tony Nguyen
Browse files

igb: check timestamp validity



Add a couple of checks to make sure timestamping is on and that the
timestamp value from DMA is valid. This avoids any functional issues
that could come from a misinterpreted time stamp.

One of the functions changed doesn't need a return value added because
there was no value in checking from the calling locations.

While here, fix a couple of reverse christmas tree issues next to
the code being changed.

Fixes: f56e7bba ("igb: Pull timestamp from fragment before adding it to skb")
Fixes: 9cbc948b ("igb: add XDP support")
Signed-off-by: default avatarJesse Brandeburg <jesse.brandeburg@intel.com>
Tested-by: default avatarDave Switzer <david.switzer@intel.com>
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
parent a75519a8
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -748,7 +748,7 @@ void igb_ptp_suspend(struct igb_adapter *adapter);
void igb_ptp_rx_hang(struct igb_adapter *adapter);
void igb_ptp_tx_hang(struct igb_adapter *adapter);
void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector, struct sk_buff *skb);
void igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector, void *va,
int igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector, void *va,
			struct sk_buff *skb);
int igb_ptp_set_ts_config(struct net_device *netdev, struct ifreq *ifr);
int igb_ptp_get_ts_config(struct net_device *netdev, struct ifreq *ifr);
+6 −5
Original line number Diff line number Diff line
@@ -8302,10 +8302,11 @@ static struct sk_buff *igb_construct_skb(struct igb_ring *rx_ring,
		return NULL;

	if (unlikely(igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP))) {
		igb_ptp_rx_pktstamp(rx_ring->q_vector, xdp->data, skb);
		if (!igb_ptp_rx_pktstamp(rx_ring->q_vector, xdp->data, skb)) {
			xdp->data += IGB_TS_HDR_LEN;
			size -= IGB_TS_HDR_LEN;
		}
	}

	/* Determine available headroom for copy */
	headlen = size;
@@ -8365,7 +8366,7 @@ static struct sk_buff *igb_build_skb(struct igb_ring *rx_ring,

	/* pull timestamp out of packet data */
	if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) {
		igb_ptp_rx_pktstamp(rx_ring->q_vector, skb->data, skb);
		if (!igb_ptp_rx_pktstamp(rx_ring->q_vector, skb->data, skb))
			__skb_pull(skb, IGB_TS_HDR_LEN);
	}

+24 −7
Original line number Diff line number Diff line
@@ -856,6 +856,9 @@ static void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter)
	dev_kfree_skb_any(skb);
}

#define IGB_RET_PTP_DISABLED 1
#define IGB_RET_PTP_INVALID 2

/**
 * igb_ptp_rx_pktstamp - retrieve Rx per packet timestamp
 * @q_vector: Pointer to interrupt specific structure
@@ -864,19 +867,29 @@ static void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter)
 *
 * This function is meant to retrieve a timestamp from the first buffer of an
 * incoming frame.  The value is stored in little endian format starting on
 * byte 8.
 * byte 8
 *
 * Returns: 0 if success, nonzero if failure
 **/
void igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector, void *va,
int igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector, void *va,
			struct sk_buff *skb)
{
	__le64 *regval = (__le64 *)va;
	struct igb_adapter *adapter = q_vector->adapter;
	__le64 *regval = (__le64 *)va;
	int adjust = 0;

	if (!(adapter->ptp_flags & IGB_PTP_ENABLED))
		return IGB_RET_PTP_DISABLED;

	/* The timestamp is recorded in little endian format.
	 * DWORD: 0        1        2        3
	 * Field: Reserved Reserved SYSTIML  SYSTIMH
	 */

	/* check reserved dwords are zero, be/le doesn't matter for zero */
	if (regval[0])
		return IGB_RET_PTP_INVALID;

	igb_ptp_systim_to_hwtstamp(adapter, skb_hwtstamps(skb),
				   le64_to_cpu(regval[1]));

@@ -896,6 +909,8 @@ void igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector, void *va,
	}
	skb_hwtstamps(skb)->hwtstamp =
		ktime_sub_ns(skb_hwtstamps(skb)->hwtstamp, adjust);

	return 0;
}

/**
@@ -906,13 +921,15 @@ void igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector, void *va,
 * This function is meant to retrieve a timestamp from the internal registers
 * of the adapter and store it in the skb.
 **/
void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector,
			 struct sk_buff *skb)
void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector, struct sk_buff *skb)
{
	struct igb_adapter *adapter = q_vector->adapter;
	struct e1000_hw *hw = &adapter->hw;
	u64 regval;
	int adjust = 0;
	u64 regval;

	if (!(adapter->ptp_flags & IGB_PTP_ENABLED))
		return;

	/* If this bit is set, then the RX registers contain the time stamp. No
	 * other packet will be time stamped until we read these registers, so