* Compute the raw (non complemented) checksum of a packet. * * @param m * The pointer to the mbuf. * @param off * The offset in bytes to start the checksum. * @param len * The length in bytes of the data to checksum. * @param cksum * A pointer to the checksum, filled on success. * @return * 0 on success, -1 on error (bad length or offset). */
| 232 | * 0 on success, -1 on error (bad length or offset). |
| 233 | */ |
| 234 | static inline int |
| 235 | rte_raw_cksum_mbuf(const struct rte_mbuf *m, uint32_t off, uint32_t len, |
| 236 | uint16_t *cksum) |
| 237 | { |
| 238 | const struct rte_mbuf *seg; |
| 239 | const char *buf; |
| 240 | uint32_t sum, tmp; |
| 241 | uint32_t seglen, done; |
| 242 | |
| 243 | /* easy case: all data in the first segment */ |
| 244 | if (off + len <= rte_pktmbuf_data_len(m)) { |
| 245 | *cksum = rte_raw_cksum(rte_pktmbuf_mtod_offset(m, |
| 246 | const char *, off), len); |
| 247 | return 0; |
| 248 | } |
| 249 | |
| 250 | if (unlikely(off + len > rte_pktmbuf_pkt_len(m))) |
| 251 | return -1; /* invalid params, return a dummy value */ |
| 252 | |
| 253 | /* else browse the segment to find offset */ |
| 254 | seglen = 0; |
| 255 | for (seg = m; seg != NULL; seg = seg->next) { |
| 256 | seglen = rte_pktmbuf_data_len(seg); |
| 257 | if (off < seglen) |
| 258 | break; |
| 259 | off -= seglen; |
| 260 | } |
| 261 | RTE_ASSERT(seg != NULL); |
| 262 | if (seg == NULL) |
| 263 | return -1; |
| 264 | seglen -= off; |
| 265 | buf = rte_pktmbuf_mtod_offset(seg, const char *, off); |
| 266 | if (seglen >= len) { |
| 267 | /* all in one segment */ |
| 268 | *cksum = rte_raw_cksum(buf, len); |
| 269 | return 0; |
| 270 | } |
| 271 | |
| 272 | /* hard case: process checksum of several segments */ |
| 273 | sum = 0; |
| 274 | done = 0; |
| 275 | for (;;) { |
| 276 | tmp = __rte_raw_cksum(buf, seglen, 0); |
| 277 | if (done & 1) |
| 278 | tmp = rte_bswap16((uint16_t)tmp); |
| 279 | sum += tmp; |
| 280 | done += seglen; |
| 281 | if (done == len) |
| 282 | break; |
| 283 | seg = seg->next; |
| 284 | buf = rte_pktmbuf_mtod(seg, const char *); |
| 285 | seglen = rte_pktmbuf_data_len(seg); |
| 286 | if (seglen > len - done) |
| 287 | seglen = len - done; |
| 288 | } |
| 289 | |
| 290 | *cksum = __rte_raw_cksum_reduce(sum); |
| 291 | return 0; |
no test coverage detected