1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
3 * Copyright (c) 2016 Mellanox Technologies Ltd. All rights reserved.
4 * Copyright (c) 2015 System Fabric Works, Inc. All rights reserved.
10 /* Compute a partial ICRC for all the IB transport headers. */
11 u32
rxe_icrc_hdr(struct rxe_pkt_info
*pkt
, struct sk_buff
*skb
)
13 unsigned int bth_offset
= 0;
14 struct iphdr
*ip4h
= NULL
;
15 struct ipv6hdr
*ip6h
= NULL
;
20 int hdr_size
= sizeof(struct udphdr
) +
21 (skb
->protocol
== htons(ETH_P_IP
) ?
22 sizeof(struct iphdr
) : sizeof(struct ipv6hdr
));
23 /* pseudo header buffer size is calculate using ipv6 header size since
24 * it is bigger than ipv4
26 u8 pshdr
[sizeof(struct udphdr
) +
27 sizeof(struct ipv6hdr
) +
30 /* This seed is the result of computing a CRC with a seed of
31 * 0xfffffff and 8 bytes of 0xff representing a masked LRH.
35 if (skb
->protocol
== htons(ETH_P_IP
)) { /* IPv4 */
36 memcpy(pshdr
, ip_hdr(skb
), hdr_size
);
37 ip4h
= (struct iphdr
*)pshdr
;
38 udph
= (struct udphdr
*)(ip4h
+ 1);
41 ip4h
->check
= CSUM_MANGLED_0
;
44 memcpy(pshdr
, ipv6_hdr(skb
), hdr_size
);
45 ip6h
= (struct ipv6hdr
*)pshdr
;
46 udph
= (struct udphdr
*)(ip6h
+ 1);
48 memset(ip6h
->flow_lbl
, 0xff, sizeof(ip6h
->flow_lbl
));
50 ip6h
->hop_limit
= 0xff;
52 udph
->check
= CSUM_MANGLED_0
;
54 bth_offset
+= hdr_size
;
56 memcpy(&pshdr
[bth_offset
], pkt
->hdr
, RXE_BTH_BYTES
);
57 bth
= (struct rxe_bth
*)&pshdr
[bth_offset
];
59 /* exclude bth.resv8a */
60 bth
->qpn
|= cpu_to_be32(~BTH_QPN_MASK
);
62 length
= hdr_size
+ RXE_BTH_BYTES
;
63 crc
= rxe_crc32(pkt
->rxe
, crc
, pshdr
, length
);
65 /* And finish to compute the CRC on the remainder of the headers. */
66 crc
= rxe_crc32(pkt
->rxe
, crc
, pkt
->hdr
+ RXE_BTH_BYTES
,
67 rxe_opcode
[pkt
->opcode
].length
- RXE_BTH_BYTES
);