-}
-
-/*
- * Send as many acks as data coalesced. Every other packet when stretch
- * ACK is not enabled. Every 8 packets, if stretch ACK is enabled.
- */
-static struct mbuf*
-tcp_send_lroacks(struct tcpcb *tp, struct mbuf *m, struct tcphdr *th)
-{
- struct mbuf *mnext = NULL, *ack_chain = NULL, *tail = NULL;
- int count = 0;
- tcp_seq org_ack = ntohl(th->th_ack);
- tcp_seq prev_ack = 0;
- int tack_offset = 28; /* IPv6 and IP options not supported */
- int twin_offset = 34; /* IPv6 and IP options not supported */
- int ack_size = (tp->t_flags & TF_STRETCHACK) ?
- (maxseg_unacked * tp->t_maxseg) : (tp->t_maxseg << 1);
- int segs_acked = (tp->t_flags & TF_STRETCHACK) ? maxseg_unacked : 2;
- struct mbuf *prev_ack_pkt = NULL;
- struct socket *so = tp->t_inpcb->inp_socket;
- unsigned short winsz = ntohs(th->th_win);
- unsigned int scaled_win = winsz<<tp->rcv_scale;
- tcp_seq win_rtedge = org_ack + scaled_win;
-
- count = tp->t_lropktlen/tp->t_maxseg;
-
- prev_ack = (org_ack - tp->t_lropktlen) + ack_size;
- if (prev_ack < org_ack) {
- ack_chain = m_dup(m, M_DONTWAIT);
- if (ack_chain) {
- th->th_ack = htonl(prev_ack);
- /* Keep adv window constant for duplicated ACK packets */
- scaled_win = win_rtedge - prev_ack;
- if (scaled_win > (int32_t)(TCP_MAXWIN << tp->rcv_scale))
- scaled_win = (int32_t)(TCP_MAXWIN << tp->rcv_scale);
- th->th_win = htons(scaled_win>>tp->rcv_scale);
- if (lrodebug == 5) {
- printf("%s: win = %d winsz = %d sc = %d"
- " lro_len %d %d\n",
- __func__, scaled_win>>tp->rcv_scale, winsz,
- tp->rcv_scale, tp->t_lropktlen, count);
- }
- tail = ack_chain;
- count -= segs_acked; /* accounts for prev_ack packet */
- count = (count <= segs_acked) ? 0 : count - segs_acked;
- tcpstat.tcps_sndacks++;
- so_tc_update_stats(m, so, m_get_service_class(m));
- } else {
- return NULL;
- }
- }
- else {
- tp->t_lropktlen = 0;
- return NULL;