Skip to content

Commit 88304bb

Browse files
Wei Fanggregkh
authored andcommitted
net: enetc: update UDP checksum when updating originTimestamp field
commit bbcbc906ab7b5834c1219cd17a38d78dba904aa0 upstream. There is an issue with one-step timestamp based on UDP/IP. The peer will discard the sync packet because of the wrong UDP checksum. For ENETC v1, the software needs to update the UDP checksum when updating the originTimestamp field, so that the hardware can correctly update the UDP checksum when updating the correction field. Otherwise, the UDP checksum in the sync packet will be wrong. Fixes: 7294380 ("enetc: support PTP Sync packet one-step timestamping") Cc: [email protected] Signed-off-by: Wei Fang <[email protected]> Reviewed-by: Vladimir Oltean <[email protected]> Tested-by: Vladimir Oltean <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent c55a98d commit 88304bb

File tree

1 file changed

+34
-7
lines changed
  • drivers/net/ethernet/freescale/enetc

1 file changed

+34
-7
lines changed

drivers/net/ethernet/freescale/enetc/enetc.c

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -231,9 +231,11 @@ static int enetc_map_tx_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb)
231231
}
232232

233233
if (do_onestep_tstamp) {
234-
u32 lo, hi, val;
235-
u64 sec, nsec;
234+
__be32 new_sec_l, new_nsec;
235+
u32 lo, hi, nsec, val;
236+
__be16 new_sec_h;
236237
u8 *data;
238+
u64 sec;
237239

238240
lo = enetc_rd_hot(hw, ENETC_SICTR0);
239241
hi = enetc_rd_hot(hw, ENETC_SICTR1);
@@ -247,13 +249,38 @@ static int enetc_map_tx_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb)
247249
/* Update originTimestamp field of Sync packet
248250
* - 48 bits seconds field
249251
* - 32 bits nanseconds field
252+
*
253+
* In addition, the UDP checksum needs to be updated
254+
* by software after updating originTimestamp field,
255+
* otherwise the hardware will calculate the wrong
256+
* checksum when updating the correction field and
257+
* update it to the packet.
250258
*/
251259
data = skb_mac_header(skb);
252-
*(__be16 *)(data + offset2) =
253-
htons((sec >> 32) & 0xffff);
254-
*(__be32 *)(data + offset2 + 2) =
255-
htonl(sec & 0xffffffff);
256-
*(__be32 *)(data + offset2 + 6) = htonl(nsec);
260+
new_sec_h = htons((sec >> 32) & 0xffff);
261+
new_sec_l = htonl(sec & 0xffffffff);
262+
new_nsec = htonl(nsec);
263+
if (udp) {
264+
struct udphdr *uh = udp_hdr(skb);
265+
__be32 old_sec_l, old_nsec;
266+
__be16 old_sec_h;
267+
268+
old_sec_h = *(__be16 *)(data + offset2);
269+
inet_proto_csum_replace2(&uh->check, skb, old_sec_h,
270+
new_sec_h, false);
271+
272+
old_sec_l = *(__be32 *)(data + offset2 + 2);
273+
inet_proto_csum_replace4(&uh->check, skb, old_sec_l,
274+
new_sec_l, false);
275+
276+
old_nsec = *(__be32 *)(data + offset2 + 6);
277+
inet_proto_csum_replace4(&uh->check, skb, old_nsec,
278+
new_nsec, false);
279+
}
280+
281+
*(__be16 *)(data + offset2) = new_sec_h;
282+
*(__be32 *)(data + offset2 + 2) = new_sec_l;
283+
*(__be32 *)(data + offset2 + 6) = new_nsec;
257284

258285
/* Configure single-step register */
259286
val = ENETC_PM0_SINGLE_STEP_EN;

0 commit comments

Comments
 (0)