0001
0002
0003
0004
0005
0006
0007 #include <linux/crc32.h>
0008
0009 #include "rxe.h"
0010 #include "rxe_loc.h"
0011
0012
0013
0014
0015
0016
0017
0018 int rxe_icrc_init(struct rxe_dev *rxe)
0019 {
0020 struct crypto_shash *tfm;
0021
0022 tfm = crypto_alloc_shash("crc32", 0, 0);
0023 if (IS_ERR(tfm)) {
0024 pr_warn("failed to init crc32 algorithm err:%ld\n",
0025 PTR_ERR(tfm));
0026 return PTR_ERR(tfm);
0027 }
0028
0029 rxe->tfm = tfm;
0030
0031 return 0;
0032 }
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043 static __be32 rxe_crc32(struct rxe_dev *rxe, __be32 crc, void *next, size_t len)
0044 {
0045 __be32 icrc;
0046 int err;
0047
0048 SHASH_DESC_ON_STACK(shash, rxe->tfm);
0049
0050 shash->tfm = rxe->tfm;
0051 *(__be32 *)shash_desc_ctx(shash) = crc;
0052 err = crypto_shash_update(shash, next, len);
0053 if (unlikely(err)) {
0054 pr_warn_ratelimited("failed crc calculation, err: %d\n", err);
0055 return (__force __be32)crc32_le((__force u32)crc, next, len);
0056 }
0057
0058 icrc = *(__be32 *)shash_desc_ctx(shash);
0059 barrier_data(shash_desc_ctx(shash));
0060
0061 return icrc;
0062 }
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072 static __be32 rxe_icrc_hdr(struct sk_buff *skb, struct rxe_pkt_info *pkt)
0073 {
0074 unsigned int bth_offset = 0;
0075 struct iphdr *ip4h = NULL;
0076 struct ipv6hdr *ip6h = NULL;
0077 struct udphdr *udph;
0078 struct rxe_bth *bth;
0079 __be32 crc;
0080 int length;
0081 int hdr_size = sizeof(struct udphdr) +
0082 (skb->protocol == htons(ETH_P_IP) ?
0083 sizeof(struct iphdr) : sizeof(struct ipv6hdr));
0084
0085
0086
0087 u8 pshdr[sizeof(struct udphdr) +
0088 sizeof(struct ipv6hdr) +
0089 RXE_BTH_BYTES];
0090
0091
0092
0093
0094 crc = (__force __be32)0xdebb20e3;
0095
0096 if (skb->protocol == htons(ETH_P_IP)) {
0097 memcpy(pshdr, ip_hdr(skb), hdr_size);
0098 ip4h = (struct iphdr *)pshdr;
0099 udph = (struct udphdr *)(ip4h + 1);
0100
0101 ip4h->ttl = 0xff;
0102 ip4h->check = CSUM_MANGLED_0;
0103 ip4h->tos = 0xff;
0104 } else {
0105 memcpy(pshdr, ipv6_hdr(skb), hdr_size);
0106 ip6h = (struct ipv6hdr *)pshdr;
0107 udph = (struct udphdr *)(ip6h + 1);
0108
0109 memset(ip6h->flow_lbl, 0xff, sizeof(ip6h->flow_lbl));
0110 ip6h->priority = 0xf;
0111 ip6h->hop_limit = 0xff;
0112 }
0113 udph->check = CSUM_MANGLED_0;
0114
0115 bth_offset += hdr_size;
0116
0117 memcpy(&pshdr[bth_offset], pkt->hdr, RXE_BTH_BYTES);
0118 bth = (struct rxe_bth *)&pshdr[bth_offset];
0119
0120
0121 bth->qpn |= cpu_to_be32(~BTH_QPN_MASK);
0122
0123 length = hdr_size + RXE_BTH_BYTES;
0124 crc = rxe_crc32(pkt->rxe, crc, pshdr, length);
0125
0126
0127 crc = rxe_crc32(pkt->rxe, crc, pkt->hdr + RXE_BTH_BYTES,
0128 rxe_opcode[pkt->opcode].length - RXE_BTH_BYTES);
0129 return crc;
0130 }
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140 int rxe_icrc_check(struct sk_buff *skb, struct rxe_pkt_info *pkt)
0141 {
0142 __be32 *icrcp;
0143 __be32 pkt_icrc;
0144 __be32 icrc;
0145
0146 icrcp = (__be32 *)(pkt->hdr + pkt->paylen - RXE_ICRC_SIZE);
0147 pkt_icrc = *icrcp;
0148
0149 icrc = rxe_icrc_hdr(skb, pkt);
0150 icrc = rxe_crc32(pkt->rxe, icrc, (u8 *)payload_addr(pkt),
0151 payload_size(pkt) + bth_pad(pkt));
0152 icrc = ~icrc;
0153
0154 if (unlikely(icrc != pkt_icrc)) {
0155 if (skb->protocol == htons(ETH_P_IPV6))
0156 pr_warn_ratelimited("bad ICRC from %pI6c\n",
0157 &ipv6_hdr(skb)->saddr);
0158 else if (skb->protocol == htons(ETH_P_IP))
0159 pr_warn_ratelimited("bad ICRC from %pI4\n",
0160 &ip_hdr(skb)->saddr);
0161 else
0162 pr_warn_ratelimited("bad ICRC from unknown\n");
0163
0164 return -EINVAL;
0165 }
0166
0167 return 0;
0168 }
0169
0170
0171
0172
0173
0174
0175 void rxe_icrc_generate(struct sk_buff *skb, struct rxe_pkt_info *pkt)
0176 {
0177 __be32 *icrcp;
0178 __be32 icrc;
0179
0180 icrcp = (__be32 *)(pkt->hdr + pkt->paylen - RXE_ICRC_SIZE);
0181 icrc = rxe_icrc_hdr(skb, pkt);
0182 icrc = rxe_crc32(pkt->rxe, icrc, (u8 *)payload_addr(pkt),
0183 payload_size(pkt) + bth_pad(pkt));
0184 *icrcp = ~icrc;
0185 }