1 /* 2 * QEMU RX packets abstractions 3 * 4 * Copyright (c) 2012 Ravello Systems LTD (http://ravellosystems.com) 5 * 6 * Developed by Daynix Computing LTD (http://www.daynix.com) 7 * 8 * Authors: 9 * Dmitry Fleytman <dmitry@daynix.com> 10 * Tamir Shomer <tamirs@daynix.com> 11 * Yan Vugenfirer <yan@daynix.com> 12 * 13 * This work is licensed under the terms of the GNU GPL, version 2 or later. 14 * See the COPYING file in the top-level directory. 15 * 16 */ 17 18 #include "qemu/osdep.h" 19 #include "trace.h" 20 #include "net_rx_pkt.h" 21 #include "net/checksum.h" 22 #include "net/tap.h" 23 24 struct NetRxPkt { 25 struct virtio_net_hdr virt_hdr; 26 uint8_t ehdr_buf[sizeof(struct eth_header) + sizeof(struct vlan_header)]; 27 struct iovec *vec; 28 uint16_t vec_len_total; 29 uint16_t vec_len; 30 uint32_t tot_len; 31 uint16_t tci; 32 size_t ehdr_buf_len; 33 eth_pkt_types_e packet_type; 34 35 /* Analysis results */ 36 bool hasip4; 37 bool hasip6; 38 39 size_t l3hdr_off; 40 size_t l4hdr_off; 41 size_t l5hdr_off; 42 43 eth_ip6_hdr_info ip6hdr_info; 44 eth_ip4_hdr_info ip4hdr_info; 45 eth_l4_hdr_info l4hdr_info; 46 }; 47 48 void net_rx_pkt_init(struct NetRxPkt **pkt) 49 { 50 struct NetRxPkt *p = g_malloc0(sizeof *p); 51 p->vec = NULL; 52 p->vec_len_total = 0; 53 *pkt = p; 54 } 55 56 void net_rx_pkt_uninit(struct NetRxPkt *pkt) 57 { 58 if (pkt->vec_len_total != 0) { 59 g_free(pkt->vec); 60 } 61 62 g_free(pkt); 63 } 64 65 struct virtio_net_hdr *net_rx_pkt_get_vhdr(struct NetRxPkt *pkt) 66 { 67 assert(pkt); 68 return &pkt->virt_hdr; 69 } 70 71 static inline void 72 net_rx_pkt_iovec_realloc(struct NetRxPkt *pkt, 73 int new_iov_len) 74 { 75 if (pkt->vec_len_total < new_iov_len) { 76 g_free(pkt->vec); 77 pkt->vec = g_malloc(sizeof(*pkt->vec) * new_iov_len); 78 pkt->vec_len_total = new_iov_len; 79 } 80 } 81 82 static void 83 net_rx_pkt_pull_data(struct NetRxPkt *pkt, 84 const struct iovec *iov, int iovcnt, 85 size_t ploff) 86 { 87 uint32_t pllen = iov_size(iov, iovcnt) - ploff; 88 89 if (pkt->ehdr_buf_len) { 90 net_rx_pkt_iovec_realloc(pkt, iovcnt + 1); 91 92 pkt->vec[0].iov_base = pkt->ehdr_buf; 93 pkt->vec[0].iov_len = pkt->ehdr_buf_len; 94 95 pkt->tot_len = pllen + pkt->ehdr_buf_len; 96 pkt->vec_len = iov_copy(pkt->vec + 1, pkt->vec_len_total - 1, 97 iov, iovcnt, ploff, pllen) + 1; 98 } else { 99 net_rx_pkt_iovec_realloc(pkt, iovcnt); 100 101 pkt->tot_len = pllen; 102 pkt->vec_len = iov_copy(pkt->vec, pkt->vec_len_total, 103 iov, iovcnt, ploff, pkt->tot_len); 104 } 105 106 eth_get_protocols(pkt->vec, pkt->vec_len, &pkt->hasip4, &pkt->hasip6, 107 &pkt->l3hdr_off, &pkt->l4hdr_off, &pkt->l5hdr_off, 108 &pkt->ip6hdr_info, &pkt->ip4hdr_info, &pkt->l4hdr_info); 109 110 trace_net_rx_pkt_parsed(pkt->hasip4, pkt->hasip6, pkt->l4hdr_info.proto, 111 pkt->l3hdr_off, pkt->l4hdr_off, pkt->l5hdr_off); 112 } 113 114 void net_rx_pkt_attach_iovec(struct NetRxPkt *pkt, 115 const struct iovec *iov, int iovcnt, 116 size_t iovoff, bool strip_vlan) 117 { 118 uint16_t tci = 0; 119 uint16_t ploff = iovoff; 120 assert(pkt); 121 122 if (strip_vlan) { 123 pkt->ehdr_buf_len = eth_strip_vlan(iov, iovcnt, iovoff, pkt->ehdr_buf, 124 &ploff, &tci); 125 } else { 126 pkt->ehdr_buf_len = 0; 127 } 128 129 pkt->tci = tci; 130 131 net_rx_pkt_pull_data(pkt, iov, iovcnt, ploff); 132 } 133 134 void net_rx_pkt_attach_iovec_ex(struct NetRxPkt *pkt, 135 const struct iovec *iov, int iovcnt, 136 size_t iovoff, bool strip_vlan, 137 uint16_t vet) 138 { 139 uint16_t tci = 0; 140 uint16_t ploff = iovoff; 141 assert(pkt); 142 143 if (strip_vlan) { 144 pkt->ehdr_buf_len = eth_strip_vlan_ex(iov, iovcnt, iovoff, vet, 145 pkt->ehdr_buf, 146 &ploff, &tci); 147 } else { 148 pkt->ehdr_buf_len = 0; 149 } 150 151 pkt->tci = tci; 152 153 net_rx_pkt_pull_data(pkt, iov, iovcnt, ploff); 154 } 155 156 void net_rx_pkt_dump(struct NetRxPkt *pkt) 157 { 158 #ifdef NET_RX_PKT_DEBUG 159 assert(pkt); 160 161 printf("RX PKT: tot_len: %d, ehdr_buf_len: %lu, vlan_tag: %d\n", 162 pkt->tot_len, pkt->ehdr_buf_len, pkt->tci); 163 #endif 164 } 165 166 void net_rx_pkt_set_packet_type(struct NetRxPkt *pkt, 167 eth_pkt_types_e packet_type) 168 { 169 assert(pkt); 170 171 pkt->packet_type = packet_type; 172 173 } 174 175 eth_pkt_types_e net_rx_pkt_get_packet_type(struct NetRxPkt *pkt) 176 { 177 assert(pkt); 178 179 return pkt->packet_type; 180 } 181 182 size_t net_rx_pkt_get_total_len(struct NetRxPkt *pkt) 183 { 184 assert(pkt); 185 186 return pkt->tot_len; 187 } 188 189 void net_rx_pkt_set_protocols(struct NetRxPkt *pkt, const void *data, 190 size_t len) 191 { 192 const struct iovec iov = { 193 .iov_base = (void *)data, 194 .iov_len = len 195 }; 196 197 assert(pkt); 198 199 eth_get_protocols(&iov, 1, &pkt->hasip4, &pkt->hasip6, 200 &pkt->l3hdr_off, &pkt->l4hdr_off, &pkt->l5hdr_off, 201 &pkt->ip6hdr_info, &pkt->ip4hdr_info, &pkt->l4hdr_info); 202 } 203 204 void net_rx_pkt_get_protocols(struct NetRxPkt *pkt, 205 bool *hasip4, bool *hasip6, 206 EthL4HdrProto *l4hdr_proto) 207 { 208 assert(pkt); 209 210 *hasip4 = pkt->hasip4; 211 *hasip6 = pkt->hasip6; 212 *l4hdr_proto = pkt->l4hdr_info.proto; 213 } 214 215 size_t net_rx_pkt_get_l3_hdr_offset(struct NetRxPkt *pkt) 216 { 217 assert(pkt); 218 return pkt->l3hdr_off; 219 } 220 221 size_t net_rx_pkt_get_l4_hdr_offset(struct NetRxPkt *pkt) 222 { 223 assert(pkt); 224 return pkt->l4hdr_off; 225 } 226 227 size_t net_rx_pkt_get_l5_hdr_offset(struct NetRxPkt *pkt) 228 { 229 assert(pkt); 230 return pkt->l5hdr_off; 231 } 232 233 eth_ip6_hdr_info *net_rx_pkt_get_ip6_info(struct NetRxPkt *pkt) 234 { 235 return &pkt->ip6hdr_info; 236 } 237 238 eth_ip4_hdr_info *net_rx_pkt_get_ip4_info(struct NetRxPkt *pkt) 239 { 240 return &pkt->ip4hdr_info; 241 } 242 243 eth_l4_hdr_info *net_rx_pkt_get_l4_info(struct NetRxPkt *pkt) 244 { 245 return &pkt->l4hdr_info; 246 } 247 248 static inline void 249 _net_rx_rss_add_chunk(uint8_t *rss_input, size_t *bytes_written, 250 void *ptr, size_t size) 251 { 252 memcpy(&rss_input[*bytes_written], ptr, size); 253 trace_net_rx_pkt_rss_add_chunk(ptr, size, *bytes_written); 254 *bytes_written += size; 255 } 256 257 static inline void 258 _net_rx_rss_prepare_ip4(uint8_t *rss_input, 259 struct NetRxPkt *pkt, 260 size_t *bytes_written) 261 { 262 struct ip_header *ip4_hdr = &pkt->ip4hdr_info.ip4_hdr; 263 264 _net_rx_rss_add_chunk(rss_input, bytes_written, 265 &ip4_hdr->ip_src, sizeof(uint32_t)); 266 267 _net_rx_rss_add_chunk(rss_input, bytes_written, 268 &ip4_hdr->ip_dst, sizeof(uint32_t)); 269 } 270 271 static inline void 272 _net_rx_rss_prepare_ip6(uint8_t *rss_input, 273 struct NetRxPkt *pkt, 274 bool ipv6ex, size_t *bytes_written) 275 { 276 eth_ip6_hdr_info *ip6info = &pkt->ip6hdr_info; 277 278 _net_rx_rss_add_chunk(rss_input, bytes_written, 279 (ipv6ex && ip6info->rss_ex_src_valid) ? &ip6info->rss_ex_src 280 : &ip6info->ip6_hdr.ip6_src, 281 sizeof(struct in6_address)); 282 283 _net_rx_rss_add_chunk(rss_input, bytes_written, 284 (ipv6ex && ip6info->rss_ex_dst_valid) ? &ip6info->rss_ex_dst 285 : &ip6info->ip6_hdr.ip6_dst, 286 sizeof(struct in6_address)); 287 } 288 289 static inline void 290 _net_rx_rss_prepare_tcp(uint8_t *rss_input, 291 struct NetRxPkt *pkt, 292 size_t *bytes_written) 293 { 294 struct tcp_header *tcphdr = &pkt->l4hdr_info.hdr.tcp; 295 296 _net_rx_rss_add_chunk(rss_input, bytes_written, 297 &tcphdr->th_sport, sizeof(uint16_t)); 298 299 _net_rx_rss_add_chunk(rss_input, bytes_written, 300 &tcphdr->th_dport, sizeof(uint16_t)); 301 } 302 303 static inline void 304 _net_rx_rss_prepare_udp(uint8_t *rss_input, 305 struct NetRxPkt *pkt, 306 size_t *bytes_written) 307 { 308 struct udp_header *udphdr = &pkt->l4hdr_info.hdr.udp; 309 310 _net_rx_rss_add_chunk(rss_input, bytes_written, 311 &udphdr->uh_sport, sizeof(uint16_t)); 312 313 _net_rx_rss_add_chunk(rss_input, bytes_written, 314 &udphdr->uh_dport, sizeof(uint16_t)); 315 } 316 317 uint32_t 318 net_rx_pkt_calc_rss_hash(struct NetRxPkt *pkt, 319 NetRxPktRssType type, 320 uint8_t *key) 321 { 322 uint8_t rss_input[36]; 323 size_t rss_length = 0; 324 uint32_t rss_hash = 0; 325 net_toeplitz_key key_data; 326 327 switch (type) { 328 case NetPktRssIpV4: 329 assert(pkt->hasip4); 330 trace_net_rx_pkt_rss_ip4(); 331 _net_rx_rss_prepare_ip4(&rss_input[0], pkt, &rss_length); 332 break; 333 case NetPktRssIpV4Tcp: 334 assert(pkt->hasip4); 335 assert(pkt->l4hdr_info.proto == ETH_L4_HDR_PROTO_TCP); 336 trace_net_rx_pkt_rss_ip4_tcp(); 337 _net_rx_rss_prepare_ip4(&rss_input[0], pkt, &rss_length); 338 _net_rx_rss_prepare_tcp(&rss_input[0], pkt, &rss_length); 339 break; 340 case NetPktRssIpV6Tcp: 341 assert(pkt->hasip6); 342 assert(pkt->l4hdr_info.proto == ETH_L4_HDR_PROTO_TCP); 343 trace_net_rx_pkt_rss_ip6_tcp(); 344 _net_rx_rss_prepare_ip6(&rss_input[0], pkt, false, &rss_length); 345 _net_rx_rss_prepare_tcp(&rss_input[0], pkt, &rss_length); 346 break; 347 case NetPktRssIpV6: 348 assert(pkt->hasip6); 349 trace_net_rx_pkt_rss_ip6(); 350 _net_rx_rss_prepare_ip6(&rss_input[0], pkt, false, &rss_length); 351 break; 352 case NetPktRssIpV6Ex: 353 assert(pkt->hasip6); 354 trace_net_rx_pkt_rss_ip6_ex(); 355 _net_rx_rss_prepare_ip6(&rss_input[0], pkt, true, &rss_length); 356 break; 357 case NetPktRssIpV6TcpEx: 358 assert(pkt->hasip6); 359 assert(pkt->l4hdr_info.proto == ETH_L4_HDR_PROTO_TCP); 360 trace_net_rx_pkt_rss_ip6_ex_tcp(); 361 _net_rx_rss_prepare_ip6(&rss_input[0], pkt, true, &rss_length); 362 _net_rx_rss_prepare_tcp(&rss_input[0], pkt, &rss_length); 363 break; 364 case NetPktRssIpV4Udp: 365 assert(pkt->hasip4); 366 assert(pkt->l4hdr_info.proto == ETH_L4_HDR_PROTO_UDP); 367 trace_net_rx_pkt_rss_ip4_udp(); 368 _net_rx_rss_prepare_ip4(&rss_input[0], pkt, &rss_length); 369 _net_rx_rss_prepare_udp(&rss_input[0], pkt, &rss_length); 370 break; 371 case NetPktRssIpV6Udp: 372 assert(pkt->hasip6); 373 assert(pkt->l4hdr_info.proto == ETH_L4_HDR_PROTO_UDP); 374 trace_net_rx_pkt_rss_ip6_udp(); 375 _net_rx_rss_prepare_ip6(&rss_input[0], pkt, false, &rss_length); 376 _net_rx_rss_prepare_udp(&rss_input[0], pkt, &rss_length); 377 break; 378 case NetPktRssIpV6UdpEx: 379 assert(pkt->hasip6); 380 assert(pkt->l4hdr_info.proto == ETH_L4_HDR_PROTO_UDP); 381 trace_net_rx_pkt_rss_ip6_ex_udp(); 382 _net_rx_rss_prepare_ip6(&rss_input[0], pkt, true, &rss_length); 383 _net_rx_rss_prepare_udp(&rss_input[0], pkt, &rss_length); 384 break; 385 default: 386 assert(false); 387 break; 388 } 389 390 net_toeplitz_key_init(&key_data, key); 391 net_toeplitz_add(&rss_hash, rss_input, rss_length, &key_data); 392 393 trace_net_rx_pkt_rss_hash(rss_length, rss_hash); 394 395 return rss_hash; 396 } 397 398 uint16_t net_rx_pkt_get_ip_id(struct NetRxPkt *pkt) 399 { 400 assert(pkt); 401 402 if (pkt->hasip4) { 403 return be16_to_cpu(pkt->ip4hdr_info.ip4_hdr.ip_id); 404 } 405 406 return 0; 407 } 408 409 bool net_rx_pkt_is_tcp_ack(struct NetRxPkt *pkt) 410 { 411 assert(pkt); 412 413 if (pkt->l4hdr_info.proto == ETH_L4_HDR_PROTO_TCP) { 414 return TCP_HEADER_FLAGS(&pkt->l4hdr_info.hdr.tcp) & TCP_FLAG_ACK; 415 } 416 417 return false; 418 } 419 420 bool net_rx_pkt_has_tcp_data(struct NetRxPkt *pkt) 421 { 422 assert(pkt); 423 424 if (pkt->l4hdr_info.proto == ETH_L4_HDR_PROTO_TCP) { 425 return pkt->l4hdr_info.has_tcp_data; 426 } 427 428 return false; 429 } 430 431 struct iovec *net_rx_pkt_get_iovec(struct NetRxPkt *pkt) 432 { 433 assert(pkt); 434 435 return pkt->vec; 436 } 437 438 uint16_t net_rx_pkt_get_iovec_len(struct NetRxPkt *pkt) 439 { 440 assert(pkt); 441 442 return pkt->vec_len; 443 } 444 445 void net_rx_pkt_set_vhdr(struct NetRxPkt *pkt, 446 struct virtio_net_hdr *vhdr) 447 { 448 assert(pkt); 449 450 memcpy(&pkt->virt_hdr, vhdr, sizeof pkt->virt_hdr); 451 } 452 453 void net_rx_pkt_set_vhdr_iovec(struct NetRxPkt *pkt, 454 const struct iovec *iov, int iovcnt) 455 { 456 assert(pkt); 457 458 iov_to_buf(iov, iovcnt, 0, &pkt->virt_hdr, sizeof pkt->virt_hdr); 459 } 460 461 void net_rx_pkt_unset_vhdr(struct NetRxPkt *pkt) 462 { 463 assert(pkt); 464 465 memset(&pkt->virt_hdr, 0, sizeof(pkt->virt_hdr)); 466 } 467 468 bool net_rx_pkt_is_vlan_stripped(struct NetRxPkt *pkt) 469 { 470 assert(pkt); 471 472 return pkt->ehdr_buf_len ? true : false; 473 } 474 475 uint16_t net_rx_pkt_get_vlan_tag(struct NetRxPkt *pkt) 476 { 477 assert(pkt); 478 479 return pkt->tci; 480 } 481 482 bool net_rx_pkt_validate_l3_csum(struct NetRxPkt *pkt, bool *csum_valid) 483 { 484 uint32_t cntr; 485 uint16_t csum; 486 uint32_t csl; 487 488 trace_net_rx_pkt_l3_csum_validate_entry(); 489 490 if (!pkt->hasip4) { 491 trace_net_rx_pkt_l3_csum_validate_not_ip4(); 492 return false; 493 } 494 495 csl = pkt->l4hdr_off - pkt->l3hdr_off; 496 497 cntr = net_checksum_add_iov(pkt->vec, pkt->vec_len, 498 pkt->l3hdr_off, 499 csl, 0); 500 501 csum = net_checksum_finish(cntr); 502 503 *csum_valid = (csum == 0); 504 505 trace_net_rx_pkt_l3_csum_validate_csum(pkt->l3hdr_off, csl, 506 cntr, csum, *csum_valid); 507 508 return true; 509 } 510 511 static uint16_t 512 _net_rx_pkt_calc_l4_csum(struct NetRxPkt *pkt) 513 { 514 uint32_t cntr; 515 uint16_t csum; 516 uint16_t csl; 517 uint32_t cso; 518 519 trace_net_rx_pkt_l4_csum_calc_entry(); 520 521 if (pkt->hasip4) { 522 if (pkt->l4hdr_info.proto == ETH_L4_HDR_PROTO_UDP) { 523 csl = be16_to_cpu(pkt->l4hdr_info.hdr.udp.uh_ulen); 524 trace_net_rx_pkt_l4_csum_calc_ip4_udp(); 525 } else { 526 csl = be16_to_cpu(pkt->ip4hdr_info.ip4_hdr.ip_len) - 527 IP_HDR_GET_LEN(&pkt->ip4hdr_info.ip4_hdr); 528 trace_net_rx_pkt_l4_csum_calc_ip4_tcp(); 529 } 530 531 cntr = eth_calc_ip4_pseudo_hdr_csum(&pkt->ip4hdr_info.ip4_hdr, 532 csl, &cso); 533 trace_net_rx_pkt_l4_csum_calc_ph_csum(cntr, csl); 534 } else { 535 if (pkt->l4hdr_info.proto == ETH_L4_HDR_PROTO_UDP) { 536 csl = be16_to_cpu(pkt->l4hdr_info.hdr.udp.uh_ulen); 537 trace_net_rx_pkt_l4_csum_calc_ip6_udp(); 538 } else { 539 struct ip6_header *ip6hdr = &pkt->ip6hdr_info.ip6_hdr; 540 size_t full_ip6hdr_len = pkt->l4hdr_off - pkt->l3hdr_off; 541 size_t ip6opts_len = full_ip6hdr_len - sizeof(struct ip6_header); 542 543 csl = be16_to_cpu(ip6hdr->ip6_ctlun.ip6_un1.ip6_un1_plen) - 544 ip6opts_len; 545 trace_net_rx_pkt_l4_csum_calc_ip6_tcp(); 546 } 547 548 cntr = eth_calc_ip6_pseudo_hdr_csum(&pkt->ip6hdr_info.ip6_hdr, csl, 549 pkt->ip6hdr_info.l4proto, &cso); 550 trace_net_rx_pkt_l4_csum_calc_ph_csum(cntr, csl); 551 } 552 553 cntr += net_checksum_add_iov(pkt->vec, pkt->vec_len, 554 pkt->l4hdr_off, csl, cso); 555 556 csum = net_checksum_finish_nozero(cntr); 557 558 trace_net_rx_pkt_l4_csum_calc_csum(pkt->l4hdr_off, csl, cntr, csum); 559 560 return csum; 561 } 562 563 bool net_rx_pkt_validate_l4_csum(struct NetRxPkt *pkt, bool *csum_valid) 564 { 565 uint16_t csum; 566 567 trace_net_rx_pkt_l4_csum_validate_entry(); 568 569 if (pkt->l4hdr_info.proto != ETH_L4_HDR_PROTO_TCP && 570 pkt->l4hdr_info.proto != ETH_L4_HDR_PROTO_UDP) { 571 trace_net_rx_pkt_l4_csum_validate_not_xxp(); 572 return false; 573 } 574 575 if (pkt->l4hdr_info.proto == ETH_L4_HDR_PROTO_UDP && 576 pkt->l4hdr_info.hdr.udp.uh_sum == 0) { 577 trace_net_rx_pkt_l4_csum_validate_udp_with_no_checksum(); 578 return false; 579 } 580 581 if (pkt->hasip4 && pkt->ip4hdr_info.fragment) { 582 trace_net_rx_pkt_l4_csum_validate_ip4_fragment(); 583 return false; 584 } 585 586 csum = _net_rx_pkt_calc_l4_csum(pkt); 587 588 *csum_valid = ((csum == 0) || (csum == 0xFFFF)); 589 590 trace_net_rx_pkt_l4_csum_validate_csum(*csum_valid); 591 592 return true; 593 } 594 595 bool net_rx_pkt_fix_l4_csum(struct NetRxPkt *pkt) 596 { 597 uint16_t csum = 0; 598 uint32_t l4_cso; 599 600 trace_net_rx_pkt_l4_csum_fix_entry(); 601 602 switch (pkt->l4hdr_info.proto) { 603 case ETH_L4_HDR_PROTO_TCP: 604 l4_cso = offsetof(struct tcp_header, th_sum); 605 trace_net_rx_pkt_l4_csum_fix_tcp(l4_cso); 606 break; 607 608 case ETH_L4_HDR_PROTO_UDP: 609 if (pkt->l4hdr_info.hdr.udp.uh_sum == 0) { 610 trace_net_rx_pkt_l4_csum_fix_udp_with_no_checksum(); 611 return false; 612 } 613 l4_cso = offsetof(struct udp_header, uh_sum); 614 trace_net_rx_pkt_l4_csum_fix_udp(l4_cso); 615 break; 616 617 default: 618 trace_net_rx_pkt_l4_csum_fix_not_xxp(); 619 return false; 620 } 621 622 if (pkt->hasip4 && pkt->ip4hdr_info.fragment) { 623 trace_net_rx_pkt_l4_csum_fix_ip4_fragment(); 624 return false; 625 } 626 627 /* Set zero to checksum word */ 628 iov_from_buf(pkt->vec, pkt->vec_len, 629 pkt->l4hdr_off + l4_cso, 630 &csum, sizeof(csum)); 631 632 /* Calculate L4 checksum */ 633 csum = cpu_to_be16(_net_rx_pkt_calc_l4_csum(pkt)); 634 635 /* Set calculated checksum to checksum word */ 636 iov_from_buf(pkt->vec, pkt->vec_len, 637 pkt->l4hdr_off + l4_cso, 638 &csum, sizeof(csum)); 639 640 trace_net_rx_pkt_l4_csum_fix_csum(pkt->l4hdr_off + l4_cso, csum); 641 642 return true; 643 } 644