| 443 | } |
| 444 | |
| 445 | static void |
| 446 | tcp_reass_merge_forward(struct tcpcb *tp, struct tseg_qent *ent) |
| 447 | { |
| 448 | struct tseg_qent *q, *qtmp; |
| 449 | int i; |
| 450 | tcp_seq max; |
| 451 | /* |
| 452 | * Given an entry merge forward anyplace |
| 453 | * that ent overlaps forward. |
| 454 | */ |
| 455 | |
| 456 | max = ent->tqe_start + ent->tqe_len; |
| 457 | q = TAILQ_NEXT(ent, tqe_q); |
| 458 | if (q == NULL) { |
| 459 | /* Nothing left */ |
| 460 | return; |
| 461 | } |
| 462 | TAILQ_FOREACH_FROM_SAFE(q, &tp->t_segq, tqe_q, qtmp) { |
| 463 | if (SEQ_GT(q->tqe_start, max)) { |
| 464 | /* Beyond q */ |
| 465 | break; |
| 466 | } |
| 467 | /* We have some or all that are overlapping */ |
| 468 | if (SEQ_GEQ(max, (q->tqe_start + q->tqe_len))) { |
| 469 | /* It consumes it all */ |
| 470 | tp->t_segqmbuflen -= q->tqe_mbuf_cnt; |
| 471 | m_freem(q->tqe_m); |
| 472 | TAILQ_REMOVE(&tp->t_segq, q, tqe_q); |
| 473 | uma_zfree(tcp_reass_zone, q); |
| 474 | tp->t_segqlen--; |
| 475 | continue; |
| 476 | } |
| 477 | /* |
| 478 | * Trim the q entry to dovetail to this one |
| 479 | * and then merge q into ent updating max |
| 480 | * in the process. |
| 481 | */ |
| 482 | i = max - q->tqe_start; |
| 483 | #ifdef TCP_REASS_LOGGING |
| 484 | tcp_log_reassm(tp, q, NULL, 0, i, TCP_R_LOG_TRIM, 2); |
| 485 | #endif |
| 486 | m_adj(q->tqe_m, i); |
| 487 | q->tqe_len -= i; |
| 488 | q->tqe_start += i; |
| 489 | tcp_reass_merge_into(tp, ent, q); |
| 490 | max = ent->tqe_start + ent->tqe_len; |
| 491 | } |
| 492 | #ifdef TCP_REASS_COUNTERS |
| 493 | counter_u64_add(merge_fwd, 1); |
| 494 | #endif |
| 495 | } |
| 496 | |
| 497 | static int |
| 498 | tcp_reass_overhead_of_chain(struct mbuf *m, struct mbuf **mlast) |
no test coverage detected