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

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
...@@ -748,7 +748,7 @@ void igb_ptp_suspend(struct igb_adapter *adapter); ...@@ -748,7 +748,7 @@ void igb_ptp_suspend(struct igb_adapter *adapter);
void igb_ptp_rx_hang(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_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_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); struct sk_buff *skb);
int igb_ptp_set_ts_config(struct net_device *netdev, struct ifreq *ifr); 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); int igb_ptp_get_ts_config(struct net_device *netdev, struct ifreq *ifr);
......
...@@ -8302,10 +8302,11 @@ static struct sk_buff *igb_construct_skb(struct igb_ring *rx_ring, ...@@ -8302,10 +8302,11 @@ static struct sk_buff *igb_construct_skb(struct igb_ring *rx_ring,
return NULL; return NULL;
if (unlikely(igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP))) { 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; xdp->data += IGB_TS_HDR_LEN;
size -= IGB_TS_HDR_LEN; size -= IGB_TS_HDR_LEN;
} }
}
/* Determine available headroom for copy */ /* Determine available headroom for copy */
headlen = size; headlen = size;
...@@ -8365,7 +8366,7 @@ static struct sk_buff *igb_build_skb(struct igb_ring *rx_ring, ...@@ -8365,7 +8366,7 @@ static struct sk_buff *igb_build_skb(struct igb_ring *rx_ring,
/* pull timestamp out of packet data */ /* pull timestamp out of packet data */
if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) { 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); __skb_pull(skb, IGB_TS_HDR_LEN);
} }
......
...@@ -856,6 +856,9 @@ static void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter) ...@@ -856,6 +856,9 @@ static void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter)
dev_kfree_skb_any(skb); 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 * igb_ptp_rx_pktstamp - retrieve Rx per packet timestamp
* @q_vector: Pointer to interrupt specific structure * @q_vector: Pointer to interrupt specific structure
...@@ -864,19 +867,29 @@ static void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter) ...@@ -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 * 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 * 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) struct sk_buff *skb)
{ {
__le64 *regval = (__le64 *)va;
struct igb_adapter *adapter = q_vector->adapter; struct igb_adapter *adapter = q_vector->adapter;
__le64 *regval = (__le64 *)va;
int adjust = 0; int adjust = 0;
if (!(adapter->ptp_flags & IGB_PTP_ENABLED))
return IGB_RET_PTP_DISABLED;
/* The timestamp is recorded in little endian format. /* The timestamp is recorded in little endian format.
* DWORD: 0 1 2 3 * DWORD: 0 1 2 3
* Field: Reserved Reserved SYSTIML SYSTIMH * 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), igb_ptp_systim_to_hwtstamp(adapter, skb_hwtstamps(skb),
le64_to_cpu(regval[1])); le64_to_cpu(regval[1]));
...@@ -896,6 +909,8 @@ void igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector, void *va, ...@@ -896,6 +909,8 @@ void igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector, void *va,
} }
skb_hwtstamps(skb)->hwtstamp = skb_hwtstamps(skb)->hwtstamp =
ktime_sub_ns(skb_hwtstamps(skb)->hwtstamp, adjust); 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, ...@@ -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 * This function is meant to retrieve a timestamp from the internal registers
* of the adapter and store it in the skb. * of the adapter and store it in the skb.
**/ **/
void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector, void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector, struct sk_buff *skb)
struct sk_buff *skb)
{ {
struct igb_adapter *adapter = q_vector->adapter; struct igb_adapter *adapter = q_vector->adapter;
struct e1000_hw *hw = &adapter->hw; struct e1000_hw *hw = &adapter->hw;
u64 regval;
int adjust = 0; 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 /* 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 * other packet will be time stamped until we read these registers, so
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment